<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
<meta name="generator" content="Doxygen 1.9.4"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Flow: log/async_file_logger.hpp Source File</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr id="projectrow">
  <td id="projectalign">
   <div id="projectname">Flow<span id="projectnumber">&#160;2.0.0</span>
   </div>
   <div id="projectbrief">Flow project: Full implementation reference.</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.9.4 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
var searchBox = new SearchBox("searchBox", "search",'Search','.html');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
$(function() {
  initMenu('',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
/* @license-end */
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="dir_9381a7bbd03577d6d8720c7f35c94ffa.html">log</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="headertitle"><div class="title">async_file_logger.hpp</div></div>
</div><!--header-->
<div class="contents">
<a href="async__file__logger_8hpp.html">Go to the documentation of this file.</a><div class="fragment"><div class="line"><a id="l00001" name="l00001"></a><span class="lineno">    1</span><span class="comment">/* Flow</span></div>
<div class="line"><a id="l00002" name="l00002"></a><span class="lineno">    2</span><span class="comment"> * Copyright 2023 Akamai Technologies, Inc.</span></div>
<div class="line"><a id="l00003" name="l00003"></a><span class="lineno">    3</span><span class="comment"> *</span></div>
<div class="line"><a id="l00004" name="l00004"></a><span class="lineno">    4</span><span class="comment"> * Licensed under the Apache License, Version 2.0 (the</span></div>
<div class="line"><a id="l00005" name="l00005"></a><span class="lineno">    5</span><span class="comment"> * &quot;License&quot;); you may not use this file except in</span></div>
<div class="line"><a id="l00006" name="l00006"></a><span class="lineno">    6</span><span class="comment"> * compliance with the License.  You may obtain a copy</span></div>
<div class="line"><a id="l00007" name="l00007"></a><span class="lineno">    7</span><span class="comment"> * of the License at</span></div>
<div class="line"><a id="l00008" name="l00008"></a><span class="lineno">    8</span><span class="comment"> *</span></div>
<div class="line"><a id="l00009" name="l00009"></a><span class="lineno">    9</span><span class="comment"> *   https://www.apache.org/licenses/LICENSE-2.0</span></div>
<div class="line"><a id="l00010" name="l00010"></a><span class="lineno">   10</span><span class="comment"> *</span></div>
<div class="line"><a id="l00011" name="l00011"></a><span class="lineno">   11</span><span class="comment"> * Unless required by applicable law or agreed to in</span></div>
<div class="line"><a id="l00012" name="l00012"></a><span class="lineno">   12</span><span class="comment"> * writing, software distributed under the License is</span></div>
<div class="line"><a id="l00013" name="l00013"></a><span class="lineno">   13</span><span class="comment"> * distributed on an &quot;AS IS&quot; BASIS, WITHOUT WARRANTIES OR</span></div>
<div class="line"><a id="l00014" name="l00014"></a><span class="lineno">   14</span><span class="comment"> * CONDITIONS OF ANY KIND, either express or implied.</span></div>
<div class="line"><a id="l00015" name="l00015"></a><span class="lineno">   15</span><span class="comment"> * See the License for the specific language governing</span></div>
<div class="line"><a id="l00016" name="l00016"></a><span class="lineno">   16</span><span class="comment"> * permissions and limitations under the License. */</span></div>
<div class="line"><a id="l00017" name="l00017"></a><span class="lineno">   17</span><span class="comment"></span> </div>
<div class="line"><a id="l00018" name="l00018"></a><span class="lineno">   18</span><span class="comment">/// @file</span></div>
<div class="line"><a id="l00019" name="l00019"></a><span class="lineno">   19</span><span class="comment"></span><span class="preprocessor">#pragma once</span></div>
<div class="line"><a id="l00020" name="l00020"></a><span class="lineno">   20</span> </div>
<div class="line"><a id="l00021" name="l00021"></a><span class="lineno">   21</span><span class="preprocessor">#include &quot;<a class="code" href="log_8hpp.html">flow/log/log.hpp</a>&quot;</span></div>
<div class="line"><a id="l00022" name="l00022"></a><span class="lineno">   22</span><span class="preprocessor">#include &quot;<a class="code" href="detail_2log__fwd_8hpp.html">flow/log/detail/log_fwd.hpp</a>&quot;</span></div>
<div class="line"><a id="l00023" name="l00023"></a><span class="lineno">   23</span><span class="preprocessor">#include &quot;<a class="code" href="single__thread__task__loop_8hpp.html">flow/async/single_thread_task_loop.hpp</a>&quot;</span></div>
<div class="line"><a id="l00024" name="l00024"></a><span class="lineno">   24</span><span class="preprocessor">#include &quot;<a class="code" href="util__fwd_8hpp.html">flow/util/util_fwd.hpp</a>&quot;</span></div>
<div class="line"><a id="l00025" name="l00025"></a><span class="lineno">   25</span><span class="preprocessor">#include &lt;boost/asio.hpp&gt;</span></div>
<div class="line"><a id="l00026" name="l00026"></a><span class="lineno">   26</span><span class="preprocessor">#include &lt;boost/move/unique_ptr.hpp&gt;</span></div>
<div class="line"><a id="l00027" name="l00027"></a><span class="lineno">   27</span><span class="preprocessor">#include &lt;atomic&gt;</span></div>
<div class="line"><a id="l00028" name="l00028"></a><span class="lineno">   28</span> </div>
<div class="line"><a id="l00029" name="l00029"></a><span class="lineno">   29</span><span class="keyword">namespace </span><a class="code hl_namespace" href="namespaceflow_1_1log.html">flow::log</a></div>
<div class="line"><a id="l00030" name="l00030"></a><span class="lineno">   30</span>{</div>
<div class="line"><a id="l00031" name="l00031"></a><span class="lineno">   31</span> </div>
<div class="line"><a id="l00032" name="l00032"></a><span class="lineno">   32</span><span class="comment">// Types.</span></div>
<div class="line"><a id="l00033" name="l00033"></a><span class="lineno">   33</span><span class="comment"></span> </div>
<div class="line"><a id="l00034" name="l00034"></a><span class="lineno">   34</span><span class="comment">/**</span></div>
<div class="line"><a id="l00035" name="l00035"></a><span class="lineno">   35</span><span class="comment"> * An implementation of Logger that logs messages to a given file-system path but never blocks any logging thread</span></div>
<div class="line"><a id="l00036" name="l00036"></a><span class="lineno">   36</span><span class="comment"> * for file I/O; suitable for heavy-duty file logging.  Protects against garbling due to simultaneous logging from</span></div>
<div class="line"><a id="l00037" name="l00037"></a><span class="lineno">   37</span><span class="comment"> * multiple threads.</span></div>
<div class="line"><a id="l00038" name="l00038"></a><span class="lineno">   38</span><span class="comment"> *</span></div>
<div class="line"><a id="l00039" name="l00039"></a><span class="lineno">   39</span><span class="comment"> * For file logging, the two out-of-the-box `Logger`s currently suitable are this Async_file_logger and</span></div>
<div class="line"><a id="l00040" name="l00040"></a><span class="lineno">   40</span><span class="comment"> * Simple_ostream_logger.  Vaguely speaking, Simple_ostream_logger is suitable for console (`cout`, `cerr`) output;</span></div>
<div class="line"><a id="l00041" name="l00041"></a><span class="lineno">   41</span><span class="comment"> * and, in a pinch outside of a heavy-duty production/server environment, for file (`ofstream`) output.  For heavy-duty</span></div>
<div class="line"><a id="l00042" name="l00042"></a><span class="lineno">   42</span><span class="comment"> * file logging one should use this Async_file_logger.  The primary reason is performance; this is discussed</span></div>
<div class="line"><a id="l00043" name="l00043"></a><span class="lineno">   43</span><span class="comment"> * in the Logger class doc header; note Async_file_logger logs asynchronously.</span></div>
<div class="line"><a id="l00044" name="l00044"></a><span class="lineno">   44</span><span class="comment"> * A secondary reason is additional file-logging-specific utilities -- such as</span></div>
<div class="line"><a id="l00045" name="l00045"></a><span class="lineno">   45</span><span class="comment"> * rotation -- are now or in the future going to be in Async_file_logger, as its purpose is heavy-duty file logging</span></div>
<div class="line"><a id="l00046" name="l00046"></a><span class="lineno">   46</span><span class="comment"> * specifically.</span></div>
<div class="line"><a id="l00047" name="l00047"></a><span class="lineno">   47</span><span class="comment"> *</span></div>
<div class="line"><a id="l00048" name="l00048"></a><span class="lineno">   48</span><span class="comment"> * @todo Lacking feature: Compress-as-you-log in Async_file_logger.  So, optionally, when characters are actually</span></div>
<div class="line"><a id="l00049" name="l00049"></a><span class="lineno">   49</span><span class="comment"> * written out to file-system, gzip/zip/whatever them instead of writing plain text.  (This is possible at least</span></div>
<div class="line"><a id="l00050" name="l00050"></a><span class="lineno">   50</span><span class="comment"> * for gzip.)  Background: It is common-place to compress a log file after it has been rotated (e.g., around rotation</span></div>
<div class="line"><a id="l00051" name="l00051"></a><span class="lineno">   51</span><span class="comment"> * time: F.log.1.gz -&gt; F.log.2.gz, F.log -&gt; F.log.1 -&gt; F.log.1.gz). It is more space-efficient (at least), however,</span></div>
<div class="line"><a id="l00052" name="l00052"></a><span class="lineno">   52</span><span class="comment"> * to write to F.log.gz directly already in compressed form; then rotation requires only renaming (e.g.:</span></div>
<div class="line"><a id="l00053" name="l00053"></a><span class="lineno">   53</span><span class="comment"> * F.log.1.gz -&gt; F.log.2.gz, F.log.gz [already gzipped from the start] -&gt; F.log.1.gz).</span></div>
<div class="line"><a id="l00054" name="l00054"></a><span class="lineno">   54</span><span class="comment"> *</span></div>
<div class="line"><a id="l00055" name="l00055"></a><span class="lineno">   55</span><span class="comment"> * ### Throttling ###</span></div>
<div class="line"><a id="l00056" name="l00056"></a><span class="lineno">   56</span><span class="comment"> * By default this feature is disabled, but one can enable/disable/configure it at will via throttling_cfg() mutator.</span></div>
<div class="line"><a id="l00057" name="l00057"></a><span class="lineno">   57</span><span class="comment"> * For example a viable tactic is to call it once right after construction, before any logging via `*this`; then</span></div>
<div class="line"><a id="l00058" name="l00058"></a><span class="lineno">   58</span><span class="comment"> * call it subsequently in case of dynamic config update.</span></div>
<div class="line"><a id="l00059" name="l00059"></a><span class="lineno">   59</span><span class="comment"> *</span></div>
<div class="line"><a id="l00060" name="l00060"></a><span class="lineno">   60</span><span class="comment"> * Throttling deals with the following potential problem which can occur under very heavy do_log() throughput</span></div>
<div class="line"><a id="l00061" name="l00061"></a><span class="lineno">   61</span><span class="comment"> * (lots of calls being made per unit time, probably from many threads); in practice this would typically only happen</span></div>
<div class="line"><a id="l00062" name="l00062"></a><span class="lineno">   62</span><span class="comment"> * if one sets effective verbosity to Sev::S_TRACE or more-verbose -- as `S_INFO`-or-less-verbose means</span></div>
<div class="line"><a id="l00063" name="l00063"></a><span class="lineno">   63</span><span class="comment"> * should_log() should be preventing do_log() from being called frequently.  For example one might enable TRACE</span></div>
<div class="line"><a id="l00064" name="l00064"></a><span class="lineno">   64</span><span class="comment"> * logging temporarily in production to see some details, causing a heavy do_log() execution rate.  (That said, if</span></div>
<div class="line"><a id="l00065" name="l00065"></a><span class="lineno">   65</span><span class="comment"> * your code does INFO-level logging too often, it could happen then too.  The official *convention* is to</span></div>
<div class="line"><a id="l00066" name="l00066"></a><span class="lineno">   66</span><span class="comment"> * log INFO-or-more-severe messages only if this would not meaningfully affect the overall perf and responsiveness</span></div>
<div class="line"><a id="l00067" name="l00067"></a><span class="lineno">   67</span><span class="comment"> * of the system; but sometimes mistakes are made.)</span></div>
<div class="line"><a id="l00068" name="l00068"></a><span class="lineno">   68</span><span class="comment"> *</span></div>
<div class="line"><a id="l00069" name="l00069"></a><span class="lineno">   69</span><span class="comment"> * Internally each do_log() call pushes this *log request* into a central (per `*this`) queue of log requests;</span></div>
<div class="line"><a id="l00070" name="l00070"></a><span class="lineno">   70</span><span class="comment"> * a single (per `*this`) background thread is always popping this queue ASAP, writing the message to the file,</span></div>
<div class="line"><a id="l00071" name="l00071"></a><span class="lineno">   71</span><span class="comment"> * etc., until the queue is emptied; then it sleeps until it becomes non-empty; and so on.  If many threads are</span></div>
<div class="line"><a id="l00072" name="l00072"></a><span class="lineno">   72</span><span class="comment"> * pushing messages faster than this thread can get through them, then more and more RAM</span></div>
<div class="line"><a id="l00073" name="l00073"></a><span class="lineno">   73</span><span class="comment"> * is used to store the enqueued messages.  If the throughput doesn&#39;t decrease in time, letting this central thread</span></div>
<div class="line"><a id="l00074" name="l00074"></a><span class="lineno">   74</span><span class="comment"> * catch up, then the RAM use might cause swapping and eventually out-of-memory (congestive collapse).</span></div>
<div class="line"><a id="l00075" name="l00075"></a><span class="lineno">   75</span><span class="comment"> * To be clear, unless congestive collapse is in fact reached, the system is self-correcting, in that given</span></div>
<div class="line"><a id="l00076" name="l00076"></a><span class="lineno">   76</span><span class="comment"> * a respite from the log-requests (do_log() calls), the queue size *will* get down to zero, as will the corresponding</span></div>
<div class="line"><a id="l00077" name="l00077"></a><span class="lineno">   77</span><span class="comment"> * memory use.  However, if this does not occur early enough, congestive collapse occurs.</span></div>
<div class="line"><a id="l00078" name="l00078"></a><span class="lineno">   78</span><span class="comment"> *</span></div>
<div class="line"><a id="l00079" name="l00079"></a><span class="lineno">   79</span><span class="comment"> * Throttling is a safeguard against this.  It works as follows.  There&#39;s a limit H in bytes.  We start at</span></div>
<div class="line"><a id="l00080" name="l00080"></a><span class="lineno">   80</span><span class="comment"> * Not-Throttling state.  If the memory use M grows beyond H, we enter Throttling state.  In this state, we</span></div>
<div class="line"><a id="l00081" name="l00081"></a><span class="lineno">   81</span><span class="comment"> * reject incoming log requests -- thus letting the system deal with just logging-to-file what it has queued up</span></div>
<div class="line"><a id="l00082" name="l00082"></a><span class="lineno">   82</span><span class="comment"> * (in FIFO fashion, naturally) -- until no more such queued-up requests remain.  Once the queue is empty,</span></div>
<div class="line"><a id="l00083" name="l00083"></a><span class="lineno">   83</span><span class="comment"> * we re-enter Not-Throttling state.  In other words beyond a certain total memory use, we throttle; then to exit</span></div>
<div class="line"><a id="l00084" name="l00084"></a><span class="lineno">   84</span><span class="comment"> * this state total memory use has to go down to 0, before we un-throttle.  The idea is to encourage a sawtooth</span></div>
<div class="line"><a id="l00085" name="l00085"></a><span class="lineno">   85</span><span class="comment"> * `/\/\/\` memory-use pattern when subjected to a firehose of log requests.</span></div>
<div class="line"><a id="l00086" name="l00086"></a><span class="lineno">   86</span><span class="comment"> *</span></div>
<div class="line"><a id="l00087" name="l00087"></a><span class="lineno">   87</span><span class="comment"> * @note An earlier functional design contemplated having a limit L (smaller than H; e.g., picture L = 50% of H),</span></div>
<div class="line"><a id="l00088" name="l00088"></a><span class="lineno">   88</span><span class="comment"> *       so that mem-use would need to merely get down to L to re-enter Not-Throttling state.  However, upon</span></div>
<div class="line"><a id="l00089" name="l00089"></a><span class="lineno">   89</span><span class="comment"> *       prototyping this, it became clear this hardly improved the experience, instead making it rather confusing</span></div>
<div class="line"><a id="l00090" name="l00090"></a><span class="lineno">   90</span><span class="comment"> *       to understand in action.  E.g., if there&#39;s a firehose going at full-blast, and you&#39;re fighting it by turning</span></div>
<div class="line"><a id="l00091" name="l00091"></a><span class="lineno">   91</span><span class="comment"> *       off the fire-hose and letting water drain, but then turn it on again once the container is 50% full, then the</span></div>
<div class="line"><a id="l00092" name="l00092"></a><span class="lineno">   92</span><span class="comment"> *       draining will &quot;fight&quot; the filling again, potentially losing quite decisively.  Trying to then read resulting</span></div>
<div class="line"><a id="l00093" name="l00093"></a><span class="lineno">   93</span><span class="comment"> *       logs is messy and strange, depending on the 2 rates relative to each other.  By comparison, the</span></div>
<div class="line"><a id="l00094" name="l00094"></a><span class="lineno">   94</span><span class="comment"> *       fill-drain-fill-drain `/\/\/\` pattern is straightforward to understand; and one can cleanly point out</span></div>
<div class="line"><a id="l00095" name="l00095"></a><span class="lineno">   95</span><span class="comment"> *       the minima and maxima with log messages.  Plus, less configuration/tuning with little to no functional</span></div>
<div class="line"><a id="l00096" name="l00096"></a><span class="lineno">   96</span><span class="comment"> *       loss = a good thing.</span></div>
<div class="line"><a id="l00097" name="l00097"></a><span class="lineno">   97</span><span class="comment"> *</span></div>
<div class="line"><a id="l00098" name="l00098"></a><span class="lineno">   98</span><span class="comment"> * The particular mechanic of throttling is as follows.  If throttling is enabled during a particular call to</span></div>
<div class="line"><a id="l00099" name="l00099"></a><span class="lineno">   99</span><span class="comment"> * should_log(), and if and only if should_log() would return `true` based on considerations excluding the</span></div>
<div class="line"><a id="l00100" name="l00100"></a><span class="lineno">  100</span><span class="comment"> * throttling feature, then:</span></div>
<div class="line"><a id="l00101" name="l00101"></a><span class="lineno">  101</span><span class="comment"> *</span></div>
<div class="line"><a id="l00102" name="l00102"></a><span class="lineno">  102</span><span class="comment"> *   - should_log() returns `true` in Not-Throttling state;</span></div>
<div class="line"><a id="l00103" name="l00103"></a><span class="lineno">  103</span><span class="comment"> *   - should_log() returns `false` in Throttling state;</span></div>
<div class="line"><a id="l00104" name="l00104"></a><span class="lineno">  104</span><span class="comment"> *</span></div>
<div class="line"><a id="l00105" name="l00105"></a><span class="lineno">  105</span><span class="comment"> * Since standard `FLOW_LOG_*` macros avoid do_log() (or even the evaluation of the message -- which is itself</span></div>
<div class="line"><a id="l00106" name="l00106"></a><span class="lineno">  106</span><span class="comment"> * quite expensive, possibly quite a bit more expensive than the do_log()) if should_log()</span></div>
<div class="line"><a id="l00107" name="l00107"></a><span class="lineno">  107</span><span class="comment"> * returns `false` for a given log call site, during Throttling state enqueuing of messages is blocked (letting</span></div>
<div class="line"><a id="l00108" name="l00108"></a><span class="lineno">  108</span><span class="comment"> * the logging-to-file thread catch up).  `should_log() == false` is how we turn off the firehose.</span></div>
<div class="line"><a id="l00109" name="l00109"></a><span class="lineno">  109</span><span class="comment"> *</span></div>
<div class="line"><a id="l00110" name="l00110"></a><span class="lineno">  110</span><span class="comment"> * M starts at 0.  Each do_log() (queued-up log request) increments M based on the memory-use estimate of the</span></div>
<div class="line"><a id="l00111" name="l00111"></a><span class="lineno">  111</span><span class="comment"> * message+metadata passed to do_log(); then it enqueues the log request.  Each time the background thread</span></div>
<div class="line"><a id="l00112" name="l00112"></a><span class="lineno">  112</span><span class="comment"> * actually writes out the queued-up message+metadata, it decrements M by the same value by which it was</span></div>
<div class="line"><a id="l00113" name="l00113"></a><span class="lineno">  113</span><span class="comment"> * incremented in do_log(); accordingly the log-request&#39;s memory is freed.</span></div>
<div class="line"><a id="l00114" name="l00114"></a><span class="lineno">  114</span><span class="comment"> *</span></div>
<div class="line"><a id="l00115" name="l00115"></a><span class="lineno">  115</span><span class="comment"> * This algorithm (computing M via increments and decrements; setting state to Throttling or Not-Throttling)</span></div>
<div class="line"><a id="l00116" name="l00116"></a><span class="lineno">  116</span><span class="comment"> * is carried out at all times.  However, should_log() consults the state (Throttling versus Not-Throttling), if</span></div>
<div class="line"><a id="l00117" name="l00117"></a><span class="lineno">  117</span><span class="comment"> * and only if the throttling feature is enabled at that time.  If it is not, that state is simply ignored, and</span></div>
<div class="line"><a id="l00118" name="l00118"></a><span class="lineno">  118</span><span class="comment"> * should_log() only makes the usual Config verbosity check(s); if that results in `true` then the message</span></div>
<div class="line"><a id="l00119" name="l00119"></a><span class="lineno">  119</span><span class="comment"> * is enqueued.  Therefore one can enable throttling at any time and count on its having immediate</span></div>
<div class="line"><a id="l00120" name="l00120"></a><span class="lineno">  120</span><span class="comment"> * effect based on actual memory use at that time.</span></div>
<div class="line"><a id="l00121" name="l00121"></a><span class="lineno">  121</span><span class="comment"> *</span></div>
<div class="line"><a id="l00122" name="l00122"></a><span class="lineno">  122</span><span class="comment"> * The limit H can also be reconfigured at any time.  Essentially throttling_cfg() mutator takes</span></div>
<div class="line"><a id="l00123" name="l00123"></a><span class="lineno">  123</span><span class="comment"> * 2 orthogonal sets of info: 1, whether throttling is to be possible at all (whether Throttling versus Not-Throttling</span></div>
<div class="line"><a id="l00124" name="l00124"></a><span class="lineno">  124</span><span class="comment"> * affects should_log() from now on); and 2, the limit H which controls the policy about setting</span></div>
<div class="line"><a id="l00125" name="l00125"></a><span class="lineno">  125</span><span class="comment"> * the state (Throttling versus Not-Throttling).  (2) affects the algorithm that computes that binary state; whereas</span></div>
<div class="line"><a id="l00126" name="l00126"></a><span class="lineno">  126</span><span class="comment"> * (1) affects whether that binary state actually controls whether to prevent logging to save memory or not.</span></div>
<div class="line"><a id="l00127" name="l00127"></a><span class="lineno">  127</span><span class="comment"> *</span></div>
<div class="line"><a id="l00128" name="l00128"></a><span class="lineno">  128</span><span class="comment"> * If H is modified, the binary state is reinitialized: it is set to Throttling if and only if</span></div>
<div class="line"><a id="l00129" name="l00129"></a><span class="lineno">  129</span><span class="comment"> * memory use M at that time exceeds H; else to Not-Throttling.  The state prior to the throttling_cfg() mutator call</span></div>
<div class="line"><a id="l00130" name="l00130"></a><span class="lineno">  130</span><span class="comment"> * does not matter in this situation; it is overwritten.  This avoids various annoying corner cases and ambiguities</span></div>
<div class="line"><a id="l00131" name="l00131"></a><span class="lineno">  131</span><span class="comment"> * around config updates.</span></div>
<div class="line"><a id="l00132" name="l00132"></a><span class="lineno">  132</span><span class="comment"> *</span></div>
<div class="line"><a id="l00133" name="l00133"></a><span class="lineno">  133</span><span class="comment"> * Lastly: Initially throttling is disabled, while a certain default value of H is assumed.  Hence the above</span></div>
<div class="line"><a id="l00134" name="l00134"></a><span class="lineno">  134</span><span class="comment"> * algorithm is active but has no effect, unless you call `throttling_cfg(true, ...)` to make it have effect</span></div>
<div class="line"><a id="l00135" name="l00135"></a><span class="lineno">  135</span><span class="comment"> * and/or change H.  You may use throttling_cfg() accessor and throttling_active() to get a copy of the current</span></div>
<div class="line"><a id="l00136" name="l00136"></a><span class="lineno">  136</span><span class="comment"> * config values.</span></div>
<div class="line"><a id="l00137" name="l00137"></a><span class="lineno">  137</span><span class="comment"> *</span></div>
<div class="line"><a id="l00138" name="l00138"></a><span class="lineno">  138</span><span class="comment"> * ### Thread safety ###</span></div>
<div class="line"><a id="l00139" name="l00139"></a><span class="lineno">  139</span><span class="comment"> * As noted above, simultaneous logging from multiple threads is safe from output corruption, in that</span></div>
<div class="line"><a id="l00140" name="l00140"></a><span class="lineno">  140</span><span class="comment"> * simultaneous do_log() calls for the same Logger targeting the same stream will log serially to each other.</span></div>
<div class="line"><a id="l00141" name="l00141"></a><span class="lineno">  141</span><span class="comment"> * However, if some other code or process writes to the same file, then all bets are off -- so don&#39;t.</span></div>
<div class="line"><a id="l00142" name="l00142"></a><span class="lineno">  142</span><span class="comment"> *</span></div>
<div class="line"><a id="l00143" name="l00143"></a><span class="lineno">  143</span><span class="comment"> * See thread safety notes and to-dos regarding #m_config in Simple_ostream_logger doc header.  These apply here also.</span></div>
<div class="line"><a id="l00144" name="l00144"></a><span class="lineno">  144</span><span class="comment"> *</span></div>
<div class="line"><a id="l00145" name="l00145"></a><span class="lineno">  145</span><span class="comment"> * throttling_cfg() mutator does not add any thread safety restrictions: it can be called concurrently with any</span></div>
<div class="line"><a id="l00146" name="l00146"></a><span class="lineno">  146</span><span class="comment"> * other method, including should_log(), do_log(), same-named accessor, and throttling_active().  There is one formal</span></div>
<div class="line"><a id="l00147" name="l00147"></a><span class="lineno">  147</span><span class="comment"> * exception: it must not be called concurrently with itself.</span></div>
<div class="line"><a id="l00148" name="l00148"></a><span class="lineno">  148</span><span class="comment"> *</span></div>
<div class="line"><a id="l00149" name="l00149"></a><span class="lineno">  149</span><span class="comment"> * There are no other mutable data (state), so that&#39;s that.</span></div>
<div class="line"><a id="l00150" name="l00150"></a><span class="lineno">  150</span><span class="comment"> *</span></div>
<div class="line"><a id="l00151" name="l00151"></a><span class="lineno">  151</span><span class="comment"> * ### Throttling: Functional design rationale notes ###</span></div>
<div class="line"><a id="l00152" name="l00152"></a><span class="lineno">  152</span><span class="comment"> * The throttling feature could have been designed differently (in terms of how it should act, functionally speaking),</span></div>
<div class="line"><a id="l00153" name="l00153"></a><span class="lineno">  153</span><span class="comment"> * and a couple of questions tend to come up, so let&#39;s answer here.</span></div>
<div class="line"><a id="l00154" name="l00154"></a><span class="lineno">  154</span><span class="comment"> *   - Why have the throttling algorithm always-on, even when `!throttling_active()` -- which is default at that?</span></div>
<div class="line"><a id="l00155" name="l00155"></a><span class="lineno">  155</span><span class="comment"> *     Could save cycles otherwise, no?  Answer: To begin with, the counting of the memory used (M) should be accurate</span></div>
<div class="line"><a id="l00156" name="l00156"></a><span class="lineno">  156</span><span class="comment"> *     in case it is (e.g.) high, and one changes throttling_active() to `true`.  Still, couldn&#39;t some things be</span></div>
<div class="line"><a id="l00157" name="l00157"></a><span class="lineno">  157</span><span class="comment"> *     skipped -- namely perhaps determining whether state is Throttling or Not-Throttling and logging about it -- when</span></div>
<div class="line"><a id="l00158" name="l00158"></a><span class="lineno">  158</span><span class="comment"> *     `!throttling_active()`?  Answer: Yes, and that might be a decent change in the future, as internally it might</span></div>
<div class="line"><a id="l00159" name="l00159"></a><span class="lineno">  159</span><span class="comment"> *     be possible to skip some mutex work in that situation which could be a small optimization.  It is basically</span></div>
<div class="line"><a id="l00160" name="l00160"></a><span class="lineno">  160</span><span class="comment"> *     simpler to think about and implement the existing way.  (More notes on this in internal comments.)</span></div>
<div class="line"><a id="l00161" name="l00161"></a><span class="lineno">  161</span><span class="comment"> *   - Why not get rid of throttling_active() knob entirely?  E.g., Async_file_logger::Throttling_cfg::m_hi_limit (H)</span></div>
<div class="line"><a id="l00162" name="l00162"></a><span class="lineno">  162</span><span class="comment"> *     could just be set to a huge value to have an apparently similar effect to `!throttling_active()`.  (The knob</span></div>
<div class="line"><a id="l00163" name="l00163"></a><span class="lineno">  163</span><span class="comment"> *     could still exist cosmetically speaking but just have the aforementioned effect.)  Answer: I (ygoldfel) first</span></div>
<div class="line"><a id="l00164" name="l00164"></a><span class="lineno">  164</span><span class="comment"> *     thought similarly, while others specified otherwise; but I quickly came around to agreeing with them.  It is</span></div>
<div class="line"><a id="l00165" name="l00165"></a><span class="lineno">  165</span><span class="comment"> *     nice to log about crossing the threshold H even without responding to it by throttling; it could be a signal</span></div>
<div class="line"><a id="l00166" name="l00166"></a><span class="lineno">  166</span><span class="comment"> *     for a user to look into enabling the feature.  Granted, we could also log at every 500k increment, or</span></div>
<div class="line"><a id="l00167" name="l00167"></a><span class="lineno">  167</span><span class="comment"> *     something like that; but the present setup seemed like a nice balance between power and simplicity.</span></div>
<div class="line"><a id="l00168" name="l00168"></a><span class="lineno">  168</span><span class="comment"> *</span></div>
<div class="line"><a id="l00169" name="l00169"></a><span class="lineno">  169</span><span class="comment"> * All in all, these choices are defensible but not necessarily the only good ones.</span></div>
<div class="line"><a id="l00170" name="l00170"></a><span class="lineno">  170</span><span class="comment"> *</span></div>
<div class="line"><a id="l00171" name="l00171"></a><span class="lineno">  171</span><span class="comment"> * @internal</span></div>
<div class="line"><a id="l00172" name="l00172"></a><span class="lineno">  172</span><span class="comment"> *</span></div>
<div class="line"><a id="l00173" name="l00173"></a><span class="lineno">  173</span><span class="comment"> * Implementation</span></div>
<div class="line"><a id="l00174" name="l00174"></a><span class="lineno">  174</span><span class="comment"> * --------------</span></div>
<div class="line"><a id="l00175" name="l00175"></a><span class="lineno">  175</span><span class="comment"> * The basic implementation is straightforward enough to be gleaned from reading the code and other comments.</span></div>
<div class="line"><a id="l00176" name="l00176"></a><span class="lineno">  176</span><span class="comment"> *</span></div>
<div class="line"><a id="l00177" name="l00177"></a><span class="lineno">  177</span><span class="comment"> * ### Throttling impl: The essential algorithm ###</span></div>
<div class="line"><a id="l00178" name="l00178"></a><span class="lineno">  178</span><span class="comment"> * What bears discussion is the implementation of the throttling feature.  Read on if you have interest in that</span></div>
<div class="line"><a id="l00179" name="l00179"></a><span class="lineno">  179</span><span class="comment"> * specific topic.  If so please carefully read the public section above entitled Throttling; then come back here.</span></div>
<div class="line"><a id="l00180" name="l00180"></a><span class="lineno">  180</span><span class="comment"> *</span></div>
<div class="line"><a id="l00181" name="l00181"></a><span class="lineno">  181</span><span class="comment"> * The impl of throttling writes itself based on that description, if one is allowed to use a mutex.  Then it&#39;s all</span></div>
<div class="line"><a id="l00182" name="l00182"></a><span class="lineno">  182</span><span class="comment"> * pretty simple: There are 3-4 functions to worry about:</span></div>
<div class="line"><a id="l00183" name="l00183"></a><span class="lineno">  183</span><span class="comment"> *</span></div>
<div class="line"><a id="l00184" name="l00184"></a><span class="lineno">  184</span><span class="comment"> *   - should_log(sev, component): First compute `m_serial_logger-&gt;should_log(sev, component)`; usually that will</span></div>
<div class="line"><a id="l00185" name="l00185"></a><span class="lineno">  185</span><span class="comment"> *     return `false`, so we should too.  If it returns `true`, though, then we should apply the added test of</span></div>
<div class="line"><a id="l00186" name="l00186"></a><span class="lineno">  186</span><span class="comment"> *     whether throttling should make us return `false` after all.  So:</span></div>
<div class="line"><a id="l00187" name="l00187"></a><span class="lineno">  187</span><span class="comment"> *     - Lock mutex.</span></div>
<div class="line"><a id="l00188" name="l00188"></a><span class="lineno">  188</span><span class="comment"> *       - If #m_throttling_active is `false` (feature disabled) then return `true`.  Else:</span></div>
<div class="line"><a id="l00189" name="l00189"></a><span class="lineno">  189</span><span class="comment"> *       - If #m_throttling_now is `false` (state is Not-Throttling) then return `true`.  Else:</span></div>
<div class="line"><a id="l00190" name="l00190"></a><span class="lineno">  190</span><span class="comment"> *       - Return `false`.  (Throttling feature enabled, and state is currently Throttling.)</span></div>
<div class="line"><a id="l00191" name="l00191"></a><span class="lineno">  191</span><span class="comment"> *   - `do_log(metadata, msg)`:</span></div>
<div class="line"><a id="l00192" name="l00192"></a><span class="lineno">  192</span><span class="comment"> *     - Compute `C = mem_cost(msg)` which inlines to essentially `msg.size()` + some compile-time constant.</span></div>
<div class="line"><a id="l00193" name="l00193"></a><span class="lineno">  193</span><span class="comment"> *     - Let local `bool throttling_begins = false`.</span></div>
<div class="line"><a id="l00194" name="l00194"></a><span class="lineno">  194</span><span class="comment"> *     - Lock mutex.</span></div>
<div class="line"><a id="l00195" name="l00195"></a><span class="lineno">  195</span><span class="comment"> *       - Increment `m_pending_logs_sz` by `C`.  `m_pending_logs_sz` is called M in the earlier discussion: the</span></div>
<div class="line"><a id="l00196" name="l00196"></a><span class="lineno">  196</span><span class="comment"> *         memory use estimate of things do_log() has enqueued but `really_log()` (see just below) has not</span></div>
<div class="line"><a id="l00197" name="l00197"></a><span class="lineno">  197</span><span class="comment"> *         yet dequeued and logged to file.</span></div>
<div class="line"><a id="l00198" name="l00198"></a><span class="lineno">  198</span><span class="comment"> *       - If #m_throttling_now is `false`, and we just made `m_pending_logs_sz` go from</span></div>
<div class="line"><a id="l00199" name="l00199"></a><span class="lineno">  199</span><span class="comment"> *         `&lt; m_throttling_cfg.m_hi_limit` (a/k/a H) to `&gt;= m_throttling_cfg.m_hi_limit`, then</span></div>
<div class="line"><a id="l00200" name="l00200"></a><span class="lineno">  200</span><span class="comment"> *         set #m_throttling_now to `true`; and set `throttling_begins = true`.</span></div>
<div class="line"><a id="l00201" name="l00201"></a><span class="lineno">  201</span><span class="comment"> *     - Enqueue the log-request:</span></div>
<div class="line"><a id="l00202" name="l00202"></a><span class="lineno">  202</span><span class="comment"> *       - Capture `metadata`; a copy of `msg`; and `throttling_begins`.</span></div>
<div class="line"><a id="l00203" name="l00203"></a><span class="lineno">  203</span><span class="comment"> *       - `m_async_worker.post()` the lambda which invokes `really_log()` with those 3 items as args.</span></div>
<div class="line"><a id="l00204" name="l00204"></a><span class="lineno">  204</span><span class="comment"> *   - `really_log(metadata, msg, throttling_begins)`:</span></div>
<div class="line"><a id="l00205" name="l00205"></a><span class="lineno">  205</span><span class="comment"> *     - `m_serial_logger-&gt;do_log(metadata, msg)`: write-out the actual message to the file.</span></div>
<div class="line"><a id="l00206" name="l00206"></a><span class="lineno">  206</span><span class="comment"> *     - If `throttling_begins == true`: via `m_serial_logger-&gt;do_log()` write-out a special message</span></div>
<div class="line"><a id="l00207" name="l00207"></a><span class="lineno">  207</span><span class="comment"> *       indicating that `msg` was the message causing state to earlier change from Not-Throttling to</span></div>
<div class="line"><a id="l00208" name="l00208"></a><span class="lineno">  208</span><span class="comment"> *       Throttling due to mem-use passing ceiling H at that time.</span></div>
<div class="line"><a id="l00209" name="l00209"></a><span class="lineno">  209</span><span class="comment"> *     - Compute `C = mem_cost(msg)` (same as in `do_log()` above).</span></div>
<div class="line"><a id="l00210" name="l00210"></a><span class="lineno">  210</span><span class="comment"> *     - Let local `bool throttling_ends = false`.</span></div>
<div class="line"><a id="l00211" name="l00211"></a><span class="lineno">  211</span><span class="comment"> *     - Lock mutex.</span></div>
<div class="line"><a id="l00212" name="l00212"></a><span class="lineno">  212</span><span class="comment"> *       - Decrement `m_pending_logs_sz` (a/k/a M) by `C`.</span></div>
<div class="line"><a id="l00213" name="l00213"></a><span class="lineno">  213</span><span class="comment"> *       - If #m_throttling_now is `true`, and we just made `m_pending_logs_sz` go down to 0, then</span></div>
<div class="line"><a id="l00214" name="l00214"></a><span class="lineno">  214</span><span class="comment"> *         set #m_throttling_now to `false`; and set `throttling_ends = true`.</span></div>
<div class="line"><a id="l00215" name="l00215"></a><span class="lineno">  215</span><span class="comment"> *     - If `throttling_ends == true`: via `m_serial_logger-&gt;do_log()` write-out a special message</span></div>
<div class="line"><a id="l00216" name="l00216"></a><span class="lineno">  216</span><span class="comment"> *       indicating that state has changed from Throttling to Not-Throttling due to mem-use reaching 0.</span></div>
<div class="line"><a id="l00217" name="l00217"></a><span class="lineno">  217</span><span class="comment"> *   - `throttling_cfg(active, cfg)` mutator:</span></div>
<div class="line"><a id="l00218" name="l00218"></a><span class="lineno">  218</span><span class="comment"> *     - Lock mutex.</span></div>
<div class="line"><a id="l00219" name="l00219"></a><span class="lineno">  219</span><span class="comment"> *       - Save args into #m_throttling_active and #m_throttling_cfg respectively.</span></div>
<div class="line"><a id="l00220" name="l00220"></a><span class="lineno">  220</span><span class="comment"> *       - If the latter&#39;s contained value (H) changed:</span></div>
<div class="line"><a id="l00221" name="l00221"></a><span class="lineno">  221</span><span class="comment"> *         - Assign `m_throttling_now = (m_pending_logs_sz &gt;= m_throttling_cfg.m_hi_limit)`.</span></div>
<div class="line"><a id="l00222" name="l00222"></a><span class="lineno">  222</span><span class="comment"> *           This reinitializes the state machine cleanly as promised in the class doc header public section.</span></div>
<div class="line"><a id="l00223" name="l00223"></a><span class="lineno">  223</span><span class="comment"> *</span></div>
<div class="line"><a id="l00224" name="l00224"></a><span class="lineno">  224</span><span class="comment"> * The mutex makes everything easy.  However the resulting perf is potentially unacceptable, at least</span></div>
<div class="line"><a id="l00225" name="l00225"></a><span class="lineno">  225</span><span class="comment"> * because should_log() is called *very* frequently from *many* threads and has a mutex lock now.</span></div>
<div class="line"><a id="l00226" name="l00226"></a><span class="lineno">  226</span><span class="comment"> * We must strive to keep computational overhead in should_log() very low; and avoid extra lock contention</span></div>
<div class="line"><a id="l00227" name="l00227"></a><span class="lineno">  227</span><span class="comment"> * if possible, especially to the extent it would affect should_log().  Onward:</span></div>
<div class="line"><a id="l00228" name="l00228"></a><span class="lineno">  228</span><span class="comment"> *</span></div>
<div class="line"><a id="l00229" name="l00229"></a><span class="lineno">  229</span><span class="comment"> * ### Throttling impl: The algorithm modified to become lock-free in should_log() ###</span></div>
<div class="line"><a id="l00230" name="l00230"></a><span class="lineno">  230</span><span class="comment"> * The easiest way to reduce critical section in should_log() concerns access to #m_throttling_active.</span></div>
<div class="line"><a id="l00231" name="l00231"></a><span class="lineno">  231</span><span class="comment"> * Suppose we make it `atomic&lt;bool&gt;` instead of `bool` with mutex protection.  If we store with `relaxed` ordering</span></div>
<div class="line"><a id="l00232" name="l00232"></a><span class="lineno">  232</span><span class="comment"> * and load with `relaxed` ordering, and do both outside any shared mutex-lock section:</span></div>
<div class="line"><a id="l00233" name="l00233"></a><span class="lineno">  233</span><span class="comment"> * throttling_cfg() mutator does the quite-rare storing; should_log() does the possibly-frequent (albeit gated by</span></div>
<div class="line"><a id="l00234" name="l00234"></a><span class="lineno">  234</span><span class="comment"> * `m_serial_logger-&gt;should_log() == true` in the first place) loading.  The `relaxed` order means</span></div>
<div class="line"><a id="l00235" name="l00235"></a><span class="lineno">  235</span><span class="comment"> * at worst there&#39;s a bit of a delay for some threads noticing the config change; so this or that thread might</span></div>
<div class="line"><a id="l00236" name="l00236"></a><span class="lineno">  236</span><span class="comment"> * throttle or not-throttle a tiny bit of time after another: it&#39;s absolutely not a problem.  Moreover there is</span></div>
<div class="line"><a id="l00237" name="l00237"></a><span class="lineno">  237</span><span class="comment"> * ~zero penalty to a `relaxed` load of `atomic&lt;bool&gt;` compared to simply accessing a `bool`.  Adding a `bool` check</span></div>
<div class="line"><a id="l00238" name="l00238"></a><span class="lineno">  238</span><span class="comment"> * to should_log() is not nothing, but it&#39;s very close.</span></div>
<div class="line"><a id="l00239" name="l00239"></a><span class="lineno">  239</span><span class="comment"> *</span></div>
<div class="line"><a id="l00240" name="l00240"></a><span class="lineno">  240</span><span class="comment"> * The only now-remaining thing in the mutex-lock section of should_log() (see pseudocode above) is the</span></div>
<div class="line"><a id="l00241" name="l00241"></a><span class="lineno">  241</span><span class="comment"> * Boolean check of #m_throttling_now.  There is exactly one consumer of this Boolean: should_log().  Again</span></div>
<div class="line"><a id="l00242" name="l00242"></a><span class="lineno">  242</span><span class="comment"> * let&#39;s replace `bool m_throttling_now` with `atomic&lt;bool&gt; m_throttling_now`; and load it with `relaxed`</span></div>
<div class="line"><a id="l00243" name="l00243"></a><span class="lineno">  243</span><span class="comment"> * ordering in should_log(), outside any shared mutex-lock section.  There are exactly 3 assigners: do_log()</span></div>
<div class="line"><a id="l00244" name="l00244"></a><span class="lineno">  244</span><span class="comment"> * and `really_log()`; they assign this when M 1st goes up past H (assign `true`) or 1st down to 0</span></div>
<div class="line"><a id="l00245" name="l00245"></a><span class="lineno">  245</span><span class="comment"> * (assign `false`) respectively; and throttling_cfg() mutator (assign depending on where M is compared to</span></div>
<div class="line"><a id="l00246" name="l00246"></a><span class="lineno">  246</span><span class="comment"> * the new H).  So let&#39;s assume -- and we&#39;ll discuss the bejesus out of it below -- we ensure the assigning</span></div>
<div class="line"><a id="l00247" name="l00247"></a><span class="lineno">  247</span><span class="comment"> * algorithm among those 3 places is made to work properly, meaning #m_throttling_now (Throttling versus</span></div>
<div class="line"><a id="l00248" name="l00248"></a><span class="lineno">  248</span><span class="comment"> * Not-Throttling state) algorithm is made to correctly set the flag&#39;s value correctly in and of itself.  Then</span></div>
<div class="line"><a id="l00249" name="l00249"></a><span class="lineno">  249</span><span class="comment"> * should_log() merely needs to read #m_throttling_now and check it against `true` to return `should_log() ==</span></div>
<div class="line"><a id="l00250" name="l00250"></a><span class="lineno">  250</span><span class="comment"> * false` iff so.  Once again, if `relaxed` ordering causes some threads to &quot;see&quot; a new value a little later</span></div>
<div class="line"><a id="l00251" name="l00251"></a><span class="lineno">  251</span><span class="comment"> * than others, that is perfectly fine.  (We re-emphasize that the 3 mutating assignment events are hardly</span></div>
<div class="line"><a id="l00252" name="l00252"></a><span class="lineno">  252</span><span class="comment"> * frequent: only when passing H going up for the 1st time since being 0, reaching 0 for the 1st time since</span></div>
<div class="line"><a id="l00253" name="l00253"></a><span class="lineno">  253</span><span class="comment"> * being &gt;= H, and possibly in throttling_cfg() mutator call.)</span></div>
<div class="line"><a id="l00254" name="l00254"></a><span class="lineno">  254</span><span class="comment"> *</span></div>
<div class="line"><a id="l00255" name="l00255"></a><span class="lineno">  255</span><span class="comment"> * Now the critical section in should_log() has been emptied: so no more mutex locking or unlocking needed in it.</span></div>
<div class="line"><a id="l00256" name="l00256"></a><span class="lineno">  256</span><span class="comment"> *</span></div>
<div class="line"><a id="l00257" name="l00257"></a><span class="lineno">  257</span><span class="comment"> * @note Note well!  The lock-free, low-overhead nature of should_log() as described in the preceding 3 paragraphs is</span></div>
<div class="line"><a id="l00258" name="l00258"></a><span class="lineno">  258</span><span class="comment"> *       **by far** the most important perf achievement of this algorithm.  Having achieved that, we&#39;ve solved what&#39;s</span></div>
<div class="line"><a id="l00259" name="l00259"></a><span class="lineno">  259</span><span class="comment"> *       almost certainly the only perf objective that really matters.  The only other code area that could conceivably</span></div>
<div class="line"><a id="l00260" name="l00260"></a><span class="lineno">  260</span><span class="comment"> *       matter perf-wise is do_log() -- and it does conceivably matter but not very much in practice.</span></div>
<div class="line"><a id="l00261" name="l00261"></a><span class="lineno">  261</span><span class="comment"> *       Please remember: do_log() is already a heavy-weight operation; before it is</span></div>
<div class="line"><a id="l00262" name="l00262"></a><span class="lineno">  262</span><span class="comment"> *       even called, the `FLOW_LOG_*()` macro almost certainly invoking it must perform expensive `ostream` assembly</span></div>
<div class="line"><a id="l00263" name="l00263"></a><span class="lineno">  263</span><span class="comment"> *       of `msg`; then do_log() itself needs to make a copy of `msg` and create an `std::function&lt;&gt;` with a number of</span></div>
<div class="line"><a id="l00264" name="l00264"></a><span class="lineno">  264</span><span class="comment"> *       captures, and enqueue all that into a boost.asio queue (which internally involves a mutex lock/unlock).  That&#39;s</span></div>
<div class="line"><a id="l00265" name="l00265"></a><span class="lineno">  265</span><span class="comment"> *       why should_log() is a separate call: by being very fast and usually returning `false`, most *potential*</span></div>
<div class="line"><a id="l00266" name="l00266"></a><span class="lineno">  266</span><span class="comment"> *       do_log() calls -- *and* the `msg` assembly (and more) *potentially* preceding each -- never happen at all:</span></div>
<div class="line"><a id="l00267" name="l00267"></a><span class="lineno">  267</span><span class="comment"> *       `FLOW_LOG_...()` essentially has the form `if (should_log(...)) { ...prep msg and mdt...; do_log(mdt, msg); }`.</span></div>
<div class="line"><a id="l00268" name="l00268"></a><span class="lineno">  268</span><span class="comment"> *       So we *should* strive to keep added throttling-algorithm-driven overhead in do_log() low and minimize</span></div>
<div class="line"><a id="l00269" name="l00269"></a><span class="lineno">  269</span><span class="comment"> *       mutex-locked critical sections therein; but such striving is a nicety, whereas optimizing should_log()</span></div>
<div class="line"><a id="l00270" name="l00270"></a><span class="lineno">  270</span><span class="comment"> *       is a necessity.</span></div>
<div class="line"><a id="l00271" name="l00271"></a><span class="lineno">  271</span><span class="comment"> *</span></div>
<div class="line"><a id="l00272" name="l00272"></a><span class="lineno">  272</span><span class="comment"> * So: We&#39;ve now reduced the algorithm to:</span></div>
<div class="line"><a id="l00273" name="l00273"></a><span class="lineno">  273</span><span class="comment"> *</span></div>
<div class="line"><a id="l00274" name="l00274"></a><span class="lineno">  274</span><span class="comment"> *   - `do_log(metadata, msg)`:</span></div>
<div class="line"><a id="l00275" name="l00275"></a><span class="lineno">  275</span><span class="comment"> *     - Compute `C = mem_cost(msg)` (add a few things including `msg.size()`).</span></div>
<div class="line"><a id="l00276" name="l00276"></a><span class="lineno">  276</span><span class="comment"> *     - Let local `bool throttling_begins = false`.</span></div>
<div class="line"><a id="l00277" name="l00277"></a><span class="lineno">  277</span><span class="comment"> *     - Lock mutex.</span></div>
<div class="line"><a id="l00278" name="l00278"></a><span class="lineno">  278</span><span class="comment"> *       - `m_pending_logs_sz += C`.</span></div>
<div class="line"><a id="l00279" name="l00279"></a><span class="lineno">  279</span><span class="comment"> *       - If #m_throttling_now is `false`, and we just made `m_pending_logs_sz` go from</span></div>
<div class="line"><a id="l00280" name="l00280"></a><span class="lineno">  280</span><span class="comment"> *         `&lt; m_throttling_cfg.m_hi_limit` to `&gt;= m_throttling_cfg.m_hi_limit`, then</span></div>
<div class="line"><a id="l00281" name="l00281"></a><span class="lineno">  281</span><span class="comment"> *         set #m_throttling_now to `true`; and set `throttling_begins = true`.</span></div>
<div class="line"><a id="l00282" name="l00282"></a><span class="lineno">  282</span><span class="comment"> *     - Enqueue the log-request:</span></div>
<div class="line"><a id="l00283" name="l00283"></a><span class="lineno">  283</span><span class="comment"> *       - Capture `metadata`; a copy of `msg`; and `throttling_begins`.</span></div>
<div class="line"><a id="l00284" name="l00284"></a><span class="lineno">  284</span><span class="comment"> *       - `m_async_worker.post()` the lambda which invokes `really_log()` with those 3 items as inputs.</span></div>
<div class="line"><a id="l00285" name="l00285"></a><span class="lineno">  285</span><span class="comment"> *   - `really_log(metadata, msg, throttling_begins)`:</span></div>
<div class="line"><a id="l00286" name="l00286"></a><span class="lineno">  286</span><span class="comment"> *     - `m_serial_logger-&gt;do_log(metadata, msg)`.</span></div>
<div class="line"><a id="l00287" name="l00287"></a><span class="lineno">  287</span><span class="comment"> *     - If `throttling_begins == true`: via `m_serial_logger-&gt;do_log()` write-out a special message</span></div>
<div class="line"><a id="l00288" name="l00288"></a><span class="lineno">  288</span><span class="comment"> *       indicating that `msg` was the message causing state to earlier change from Not-Throttling to</span></div>
<div class="line"><a id="l00289" name="l00289"></a><span class="lineno">  289</span><span class="comment"> *       Throttling due to mem-use passing ceiling H at that time.</span></div>
<div class="line"><a id="l00290" name="l00290"></a><span class="lineno">  290</span><span class="comment"> *     - Compute `C = mem_cost(msg)`.</span></div>
<div class="line"><a id="l00291" name="l00291"></a><span class="lineno">  291</span><span class="comment"> *     - Let local `bool throttling_ends = false`.</span></div>
<div class="line"><a id="l00292" name="l00292"></a><span class="lineno">  292</span><span class="comment"> *     - Lock mutex.</span></div>
<div class="line"><a id="l00293" name="l00293"></a><span class="lineno">  293</span><span class="comment"> *       - `m_pending_logs_sz -= C`.</span></div>
<div class="line"><a id="l00294" name="l00294"></a><span class="lineno">  294</span><span class="comment"> *       - If #m_throttling_now is `true`, and we just made `m_pending_logs_sz == 0`,</span></div>
<div class="line"><a id="l00295" name="l00295"></a><span class="lineno">  295</span><span class="comment"> *         then set #m_throttling_now to `false`; and set `throttling_ends = true`.</span></div>
<div class="line"><a id="l00296" name="l00296"></a><span class="lineno">  296</span><span class="comment"> *     - If `throttling_ends == true`: via `m_serial_logger-&gt;do_log()` write-out:</span></div>
<div class="line"><a id="l00297" name="l00297"></a><span class="lineno">  297</span><span class="comment"> *       state has changed from Throttling to Not-Throttling due to mem-use use reaching 0.</span></div>
<div class="line"><a id="l00298" name="l00298"></a><span class="lineno">  298</span><span class="comment"> *   - `throttling_cfg(active, cfg)` mutator:</span></div>
<div class="line"><a id="l00299" name="l00299"></a><span class="lineno">  299</span><span class="comment"> *     - Save `m_throttling_active = active`.</span></div>
<div class="line"><a id="l00300" name="l00300"></a><span class="lineno">  300</span><span class="comment"> *     - Lock mutex.</span></div>
<div class="line"><a id="l00301" name="l00301"></a><span class="lineno">  301</span><span class="comment"> *       - Save `m_throttling_cfg = cfg`.</span></div>
<div class="line"><a id="l00302" name="l00302"></a><span class="lineno">  302</span><span class="comment"> *       - If the latter&#39;s contained value (H) changed:</span></div>
<div class="line"><a id="l00303" name="l00303"></a><span class="lineno">  303</span><span class="comment"> *         - Assign `m_throttling_now = (m_pending_logs_sz &gt;= m_throttling_cfg.m_hi_limit)`.</span></div>
<div class="line"><a id="l00304" name="l00304"></a><span class="lineno">  304</span><span class="comment"> *</span></div>
<div class="line"><a id="l00305" name="l00305"></a><span class="lineno">  305</span><span class="comment"> * That&#39;s acceptable, because the really important (for perf) place, should_log(), now is lock-free</span></div>
<div class="line"><a id="l00306" name="l00306"></a><span class="lineno">  306</span><span class="comment"> * with the added overhead being 2 mere checks against zero; and even then only if the core `should_log()` yielded</span></div>
<div class="line"><a id="l00307" name="l00307"></a><span class="lineno">  307</span><span class="comment"> * `true` -- which usually it doesn&#39;t.</span></div>
<div class="line"><a id="l00308" name="l00308"></a><span class="lineno">  308</span><span class="comment"> *</span></div>
<div class="line"><a id="l00309" name="l00309"></a><span class="lineno">  309</span><span class="comment"> * Let&#39;s reassert that the overhead and potential lock contention added on account of the throttling logic</span></div>
<div class="line"><a id="l00310" name="l00310"></a><span class="lineno">  310</span><span class="comment"> * in do_log() are minor.  (If so, then `really_log()` and throttling_cfg() mutator need not be scrutinized much, as</span></div>
<div class="line"><a id="l00311" name="l00311"></a><span class="lineno">  311</span><span class="comment"> * they matter less and much less respectively.)  We&#39;ve already noted this, but let&#39;s make sure.</span></div>
<div class="line"><a id="l00312" name="l00312"></a><span class="lineno">  312</span><span class="comment"> *</span></div>
<div class="line"><a id="l00313" name="l00313"></a><span class="lineno">  313</span><span class="comment"> *   - Added cycles (assuming no lock contention): To enumerate this overhead:</span></div>
<div class="line"><a id="l00314" name="l00314"></a><span class="lineno">  314</span><span class="comment"> *     - mem_cost().  This adds `msg.size()` (a `size_t` memory value) to a compile-time constant, more or less.</span></div>
<div class="line"><a id="l00315" name="l00315"></a><span class="lineno">  315</span><span class="comment"> *     - Increment M by that number (`+=` with saving a `prev_val` and resulting `new_val`).</span></div>
<div class="line"><a id="l00316" name="l00316"></a><span class="lineno">  316</span><span class="comment"> *     - Check a `bool`.</span></div>
<div class="line"><a id="l00317" name="l00317"></a><span class="lineno">  317</span><span class="comment"> *       - Possibly compare `prev_val &lt; H` and `new_val &gt;= H`.</span></div>
<div class="line"><a id="l00318" name="l00318"></a><span class="lineno">  318</span><span class="comment"> *     - Set `bool throttling_begins` to `true` or `false` accordingly.</span></div>
<div class="line"><a id="l00319" name="l00319"></a><span class="lineno">  319</span><span class="comment"> *     - Add `throttling_begins` in addition to the existing payload into Log_request (which is</span></div>
<div class="line"><a id="l00320" name="l00320"></a><span class="lineno">  320</span><span class="comment"> *       2 pointers + 1 `size_t`) which is packaged together with the task.</span></div>
<div class="line"><a id="l00321" name="l00321"></a><span class="lineno">  321</span><span class="comment"> *     - Mutex lock/unlock.  (We&#39;re assuming no lock contention; so this is cheap.)</span></div>
<div class="line"><a id="l00322" name="l00322"></a><span class="lineno">  322</span><span class="comment"> *     - CONCLUSION: It&#39;s 5-ish increments, 2-ish integer comparisons, copying a ~handful of scalars ~1x each, and</span></div>
<div class="line"><a id="l00323" name="l00323"></a><span class="lineno">  323</span><span class="comment"> *       change.  Compare to the &quot;Enqueue the log-request&quot; step alone: create `function&lt;&gt;`</span></div>
<div class="line"><a id="l00324" name="l00324"></a><span class="lineno">  324</span><span class="comment"> *       object, enqueue it to boost.asio task queue -- copying `msg` and other parts of Log_request in the process.</span></div>
<div class="line"><a id="l00325" name="l00325"></a><span class="lineno">  325</span><span class="comment"> *       Now throw in the `ostream&lt;&lt;` manipulation needed to assemble `msg`; the time spent heap-allocating + populating</span></div>
<div class="line"><a id="l00326" name="l00326"></a><span class="lineno">  326</span><span class="comment"> *       Msg_metadata, such as allocating and copying thread nickname, if it&#39;s long enough.  And lastly remember</span></div>
<div class="line"><a id="l00327" name="l00327"></a><span class="lineno">  327</span><span class="comment"> *       that the should_log() mechanism (even *without* any throttling) is</span></div>
<div class="line"><a id="l00328" name="l00328"></a><span class="lineno">  328</span><span class="comment"> *       normally supposed to make do_log() calls so infrequent that the processor cycle cost is small in the</span></div>
<div class="line"><a id="l00329" name="l00329"></a><span class="lineno">  329</span><span class="comment"> *       first place.  Conclusion: Yes, this overhead is acceptable: it is small as a %; and in absolute terms,</span></div>
<div class="line"><a id="l00330" name="l00330"></a><span class="lineno">  330</span><span class="comment"> *       the latter only conceivably not being the case, if it would have been not the case anyway (and not in a</span></div>
<div class="line"><a id="l00331" name="l00331"></a><span class="lineno">  331</span><span class="comment"> *       well functioning system).</span></div>
<div class="line"><a id="l00332" name="l00332"></a><span class="lineno">  332</span><span class="comment"> *   - Lock contention: The critical section is similar in both potentially contending pieces of code</span></div>
<div class="line"><a id="l00333" name="l00333"></a><span class="lineno">  333</span><span class="comment"> *     (do_log() and `really_log()`); so let&#39;s take the one in do_log().  It is *tiny*:</span></div>
<div class="line"><a id="l00334" name="l00334"></a><span class="lineno">  334</span><span class="comment"> *     Integer add and ~3 assignments; Boolean comparison; possibly 1-2 integer comparisons; and either a short jump</span></div>
<div class="line"><a id="l00335" name="l00335"></a><span class="lineno">  335</span><span class="comment"> *     or 2 more Boolean assignments.</span></div>
<div class="line"><a id="l00336" name="l00336"></a><span class="lineno">  336</span><span class="comment"> *     - It&#39;s tiny in absolute terms.</span></div>
<div class="line"><a id="l00337" name="l00337"></a><span class="lineno">  337</span><span class="comment"> *     - It&#39;s tiny in % terms, as discussed earlier for do_log().  (In `really_log()` it&#39;s even more so, as it is</span></div>
<div class="line"><a id="l00338" name="l00338"></a><span class="lineno">  338</span><span class="comment"> *       all in one thread *and* doing synchronous file I/O.)</span></div>
<div class="line"><a id="l00339" name="l00339"></a><span class="lineno">  339</span><span class="comment"> *     - do_log() already has a boost.asio task queue push with mutex lock/unlock, contending against `really_log()`</span></div>
<div class="line"><a id="l00340" name="l00340"></a><span class="lineno">  340</span><span class="comment"> *       performing mutex lock/unlock + queue pop; plus condition-variable wait/notify.  Even under very intense</span></div>
<div class="line"><a id="l00341" name="l00341"></a><span class="lineno">  341</span><span class="comment"> *       practical logging scenarios, lock contention from this critical section was never observed to be a factor.</span></div>
<div class="line"><a id="l00342" name="l00342"></a><span class="lineno">  342</span><span class="comment"> *     - CONCLUSION: It would be very surprising if this added locking ever caused any observable contention.</span></div>
<div class="line"><a id="l00343" name="l00343"></a><span class="lineno">  343</span><span class="comment"> *</span></div>
<div class="line"><a id="l00344" name="l00344"></a><span class="lineno">  344</span><span class="comment"> * @note I (ygoldfel) heavily pursued a completely lock-free solution.  I got tantalizingly close.  It involved</span></div>
<div class="line"><a id="l00345" name="l00345"></a><span class="lineno">  345</span><span class="comment"> *       an added pointer indirection in should_log() (and do_log() and `really_log()`), with a pointer</span></div>
<div class="line"><a id="l00346" name="l00346"></a><span class="lineno">  346</span><span class="comment"> *       storing throttling state `struct`, atomically replaced by `throttling_cfg()` mutator; completely removing</span></div>
<div class="line"><a id="l00347" name="l00347"></a><span class="lineno">  347</span><span class="comment"> *       mutex; and turning `m_pending_logs_sz` into an `atomic`.  Unfortunately there was a very unlikely corner</span></div>
<div class="line"><a id="l00348" name="l00348"></a><span class="lineno">  348</span><span class="comment"> *       case that was nevertheless formally possible.  Ultimately it came down to the fact that</span></div>
<div class="line"><a id="l00349" name="l00349"></a><span class="lineno">  349</span><span class="comment"> *       `A(); if (...based-on-A()...) { B(); }` and `C(); if (...based-on-C()...) { D(); }` executing concurrently,</span></div>
<div class="line"><a id="l00350" name="l00350"></a><span class="lineno">  350</span><span class="comment"> *       with `A()` being reached before `C()`, execution order can be A-C-D-B instead of the desired A-C-B-D.  In our</span></div>
<div class="line"><a id="l00351" name="l00351"></a><span class="lineno">  351</span><span class="comment"> *       case this could, formally speaking, cause `m_throttling_now =&gt; true =&gt; false` to incorrectly be switched to</span></div>
<div class="line"><a id="l00352" name="l00352"></a><span class="lineno">  352</span><span class="comment"> *       `m_throttling_now =&gt; false =&gt; true` (if, e.g., M=H is reached and then very quickly/near-concurrently M=0 is</span></div>
<div class="line"><a id="l00353" name="l00353"></a><span class="lineno">  353</span><span class="comment"> *       reached); or vice versa.  Without synchronization of some kind I couldn&#39;t make it be bullet-proof.</span></div>
<div class="line"><a id="l00354" name="l00354"></a><span class="lineno">  354</span><span class="comment"> *       (There was also the slightly longer computation in should_log(): pointer indirection to account for</span></div>
<div class="line"><a id="l00355" name="l00355"></a><span class="lineno">  355</span><span class="comment"> *       config-setting no longer being mutex-protected; but in my view that addition was acceptable still.</span></div>
<div class="line"><a id="l00356" name="l00356"></a><span class="lineno">  356</span><span class="comment"> *       Unfortunately I couldn&#39;t make the algorithm formally correct.)</span></div>
<div class="line"><a id="l00357" name="l00357"></a><span class="lineno">  357</span><span class="comment"> */</span></div>
<div class="line"><a id="l00358" name="l00358"></a><span class="lineno"><a class="line" href="classflow_1_1log_1_1Async__file__logger.html">  358</a></span><span class="keyword">class </span><a class="code hl_class" href="classflow_1_1log_1_1Async__file__logger.html">Async_file_logger</a> :</div>
<div class="line"><a id="l00359" name="l00359"></a><span class="lineno">  359</span>  <span class="keyword">public</span> <a class="code hl_class" href="classflow_1_1log_1_1Logger.html">Logger</a>,</div>
<div class="line"><a id="l00360" name="l00360"></a><span class="lineno">  360</span>  <span class="keyword">protected</span> <a class="code hl_class" href="classflow_1_1log_1_1Log__context.html">Log_context</a></div>
<div class="line"><a id="l00361" name="l00361"></a><span class="lineno">  361</span>{</div>
<div class="line"><a id="l00362" name="l00362"></a><span class="lineno">  362</span><span class="keyword">public</span>:</div>
<div class="line"><a id="l00363" name="l00363"></a><span class="lineno">  363</span>  <span class="comment">// Types.</span></div>
<div class="line"><a id="l00364" name="l00364"></a><span class="lineno">  364</span><span class="comment"></span> </div>
<div class="line"><a id="l00365" name="l00365"></a><span class="lineno">  365</span><span class="comment">  /**</span></div>
<div class="line"><a id="l00366" name="l00366"></a><span class="lineno">  366</span><span class="comment">   * Controls behavior of the throttling algorithm as described in Async_file_logger doc header Throttling section.</span></div>
<div class="line"><a id="l00367" name="l00367"></a><span class="lineno">  367</span><span class="comment">   * As noted there, value(s) therein affect the algorithm for computing Throttling versus Not-Throttling state but</span></div>
<div class="line"><a id="l00368" name="l00368"></a><span class="lineno">  368</span><span class="comment">   * *not* whether should_log() actually allows that state to have any effect.  That is controlled by a peer</span></div>
<div class="line"><a id="l00369" name="l00369"></a><span class="lineno">  369</span><span class="comment">   * argument to throttling_cfg().</span></div>
<div class="line"><a id="l00370" name="l00370"></a><span class="lineno">  370</span><span class="comment">   *</span></div>
<div class="line"><a id="l00371" name="l00371"></a><span class="lineno">  371</span><span class="comment">   * @internal</span></div>
<div class="line"><a id="l00372" name="l00372"></a><span class="lineno">  372</span><span class="comment">   * ### Rationale ###</span></div>
<div class="line"><a id="l00373" name="l00373"></a><span class="lineno">  373</span><span class="comment">   * Why the `struct` and not just expose `m_hi_limit` by itself?  Answer: there is a &quot;note&quot; about it in the</span></div>
<div class="line"><a id="l00374" name="l00374"></a><span class="lineno">  374</span><span class="comment">   * Async_file_logger class doc header.  Short answer: maintainability/future-proofing.</span></div>
<div class="line"><a id="l00375" name="l00375"></a><span class="lineno">  375</span><span class="comment">   */</span></div>
<div class="line"><a id="l00376" name="l00376"></a><span class="lineno"><a class="line" href="structflow_1_1log_1_1Async__file__logger_1_1Throttling__cfg.html">  376</a></span>  <span class="keyword">struct </span><a class="code hl_struct" href="structflow_1_1log_1_1Async__file__logger_1_1Throttling__cfg.html">Throttling_cfg</a></div>
<div class="line"><a id="l00377" name="l00377"></a><span class="lineno">  377</span>  {</div>
<div class="line"><a id="l00378" name="l00378"></a><span class="lineno">  378</span>    <span class="comment">// Data.</span></div>
<div class="line"><a id="l00379" name="l00379"></a><span class="lineno">  379</span><span class="comment"></span> </div>
<div class="line"><a id="l00380" name="l00380"></a><span class="lineno">  380</span><span class="comment">    /**</span></div>
<div class="line"><a id="l00381" name="l00381"></a><span class="lineno">  381</span><span class="comment">     * The throttling algorithm will go from Not-Throttling to Throttling state if and only if the current memory</span></div>
<div class="line"><a id="l00382" name="l00382"></a><span class="lineno">  382</span><span class="comment">     * usage changes from `&lt; m_hi_limit` to `&gt;= m_hi_limit`.</span></div>
<div class="line"><a id="l00383" name="l00383"></a><span class="lineno">  383</span><span class="comment">     * Async_file_logger doc header Throttling section calls this value H.  It must be positive.</span></div>
<div class="line"><a id="l00384" name="l00384"></a><span class="lineno">  384</span><span class="comment">     */</span></div>
<div class="line"><a id="l00385" name="l00385"></a><span class="lineno"><a class="line" href="structflow_1_1log_1_1Async__file__logger_1_1Throttling__cfg.html#a7a30343e388c65594d06baed25b1aaa9">  385</a></span>    uint64_t <a class="code hl_variable" href="structflow_1_1log_1_1Async__file__logger_1_1Throttling__cfg.html#a7a30343e388c65594d06baed25b1aaa9">m_hi_limit</a>;</div>
<div class="line"><a id="l00386" name="l00386"></a><span class="lineno">  386</span><span class="comment"></span> </div>
<div class="line"><a id="l00387" name="l00387"></a><span class="lineno">  387</span><span class="comment">    /**</span></div>
<div class="line"><a id="l00388" name="l00388"></a><span class="lineno">  388</span><span class="comment">     * Value of `Async_file_logger(...).throttling_cfg().m_hi_limit`: default/initial value of #m_hi_limit.</span></div>
<div class="line"><a id="l00389" name="l00389"></a><span class="lineno">  389</span><span class="comment">     *</span></div>
<div class="line"><a id="l00390" name="l00390"></a><span class="lineno">  390</span><span class="comment">     * Note that this value is not meant to be some kind of universally correct choice for #m_hi_limit.</span></div>
<div class="line"><a id="l00391" name="l00391"></a><span class="lineno">  391</span><span class="comment">     * Users can and should change `m_hi_limit`.</span></div>
<div class="line"><a id="l00392" name="l00392"></a><span class="lineno">  392</span><span class="comment">     */</span></div>
<div class="line"><a id="l00393" name="l00393"></a><span class="lineno"><a class="line" href="structflow_1_1log_1_1Async__file__logger_1_1Throttling__cfg.html#a72a52accb11b29307dad69748e133818">  393</a></span>    <span class="keyword">static</span> <span class="keyword">constexpr</span> uint64_t <a class="code hl_variable" href="structflow_1_1log_1_1Async__file__logger_1_1Throttling__cfg.html#a72a52accb11b29307dad69748e133818">S_HI_LIMIT_DEFAULT</a> = 1ull * 1024 * 1024 * 1024;</div>
<div class="line"><a id="l00394" name="l00394"></a><span class="lineno">  394</span>  }; <span class="comment">// struct Throttling_cfg</span></div>
<div class="line"><a id="l00395" name="l00395"></a><span class="lineno">  395</span> </div>
<div class="line"><a id="l00396" name="l00396"></a><span class="lineno">  396</span>  <span class="comment">// Constructors/destructor.</span></div>
<div class="line"><a id="l00397" name="l00397"></a><span class="lineno">  397</span><span class="comment"></span> </div>
<div class="line"><a id="l00398" name="l00398"></a><span class="lineno">  398</span><span class="comment">  /**</span></div>
<div class="line"><a id="l00399" name="l00399"></a><span class="lineno">  399</span><span class="comment">   * Constructs logger to subsequently log to the given file-system path.  It will append.</span></div>
<div class="line"><a id="l00400" name="l00400"></a><span class="lineno">  400</span><span class="comment">   *</span></div>
<div class="line"><a id="l00401" name="l00401"></a><span class="lineno">  401</span><span class="comment">   * @todo Consider adding Async_file_logger constructor option to overwrite the file instead of appending.</span></div>
<div class="line"><a id="l00402" name="l00402"></a><span class="lineno">  402</span><span class="comment">   *</span></div>
<div class="line"><a id="l00403" name="l00403"></a><span class="lineno">  403</span><span class="comment">   * @param config</span></div>
<div class="line"><a id="l00404" name="l00404"></a><span class="lineno">  404</span><span class="comment">   *        Controls behavior of this Logger.  In particular, it affects should_log() logic (verbosity default and</span></div>
<div class="line"><a id="l00405" name="l00405"></a><span class="lineno">  405</span><span class="comment">   *        per-component) and output format (such as time stamp format).  See thread safety notes in class doc header.</span></div>
<div class="line"><a id="l00406" name="l00406"></a><span class="lineno">  406</span><span class="comment">   *        This is saved in #m_config.</span></div>
<div class="line"><a id="l00407" name="l00407"></a><span class="lineno">  407</span><span class="comment">   * @param log_path</span></div>
<div class="line"><a id="l00408" name="l00408"></a><span class="lineno">  408</span><span class="comment">   *        File-system path to which to write subsequently.  Note that no writing occurs until the first do_log() call.</span></div>
<div class="line"><a id="l00409" name="l00409"></a><span class="lineno">  409</span><span class="comment">   * @param backup_logger_ptr</span></div>
<div class="line"><a id="l00410" name="l00410"></a><span class="lineno">  410</span><span class="comment">   *        The Logger to use for `*this` to log *about* its logging operations to the actual intended file-system path;</span></div>
<div class="line"><a id="l00411" name="l00411"></a><span class="lineno">  411</span><span class="comment">   *        or null to not log such things anywhere.  If you do not pass in null, but ensure</span></div>
<div class="line"><a id="l00412" name="l00412"></a><span class="lineno">  412</span><span class="comment">   *        `backup_logger_ptr-&gt;should_log()` lets through nothing more than `Sev::S_INFO` severity messages for</span></div>
<div class="line"><a id="l00413" name="l00413"></a><span class="lineno">  413</span><span class="comment">   *        `Flow_log_component::S_LOG`, then you can expect a reasonable amount of useful output that will not</span></div>
<div class="line"><a id="l00414" name="l00414"></a><span class="lineno">  414</span><span class="comment">   *        affect performance.  Tip: null is a reasonable value.  A Simple_ostream_logger logging to `cout` and `cerr`</span></div>
<div class="line"><a id="l00415" name="l00415"></a><span class="lineno">  415</span><span class="comment">   *        (or only `cout`) is also a good choice, arguably better than null.</span></div>
<div class="line"><a id="l00416" name="l00416"></a><span class="lineno">  416</span><span class="comment">   *        Lastly, setting verbosity to `INFO` for `*backup_logger_ptr` is typically a better choice than</span></div>
<div class="line"><a id="l00417" name="l00417"></a><span class="lineno">  417</span><span class="comment">   *        `TRACE` in practice.</span></div>
<div class="line"><a id="l00418" name="l00418"></a><span class="lineno">  418</span><span class="comment">   * @param capture_rotate_signals_internally</span></div>
<div class="line"><a id="l00419" name="l00419"></a><span class="lineno">  419</span><span class="comment">   *        If and only if this is `true`, `*this` will detect SIGHUP (or your OS&#39;s version thereof);</span></div>
<div class="line"><a id="l00420" name="l00420"></a><span class="lineno">  420</span><span class="comment">   *        upon seeing such a signal, it will fire the equivalent of log_flush_and_reopen(), as needed for classic</span></div>
<div class="line"><a id="l00421" name="l00421"></a><span class="lineno">  421</span><span class="comment">   *        log rotation.  (The idea is: If we are writing to path F, then your outside log rotation tool will rename</span></div>
<div class="line"><a id="l00422" name="l00422"></a><span class="lineno">  422</span><span class="comment">   *        F -&gt; F.1 [and F.1 -&gt; F.2, etc.]; even as we continue writing to the underlying file after it has been</span></div>
<div class="line"><a id="l00423" name="l00423"></a><span class="lineno">  423</span><span class="comment">   *        renamed; then the tool sends SIGHUP; we flush/close what is really F.1; reopen at the real path F</span></div>
<div class="line"><a id="l00424" name="l00424"></a><span class="lineno">  424</span><span class="comment">   *        again, which will create it anew post-rotation.)  If `false` then you&#39;d have to do it yourself if desired.</span></div>
<div class="line"><a id="l00425" name="l00425"></a><span class="lineno">  425</span><span class="comment">   *        If this is `true`, the user may register their own signal handler(s) (for any purpose whatsoever) using</span></div>
<div class="line"><a id="l00426" name="l00426"></a><span class="lineno">  426</span><span class="comment">   *        `boost::asio::signal_set`. However, behavior is undefined if the program registers signal handlers via any</span></div>
<div class="line"><a id="l00427" name="l00427"></a><span class="lineno">  427</span><span class="comment">   *        other API, such as `sigaction()` or `signal()`.  If you need to set up such a non-`signal_set` signal</span></div>
<div class="line"><a id="l00428" name="l00428"></a><span class="lineno">  428</span><span class="comment">   *        handler, AND you require rotation behavior, then (1) set this option to `false`; (2) trap SIGHUP yourself;</span></div>
<div class="line"><a id="l00429" name="l00429"></a><span class="lineno">  429</span><span class="comment">   *        (3) in your handlers for the latter, simply call log_flush_and_reopen().  However, if typical, common-sense</span></div>
<div class="line"><a id="l00430" name="l00430"></a><span class="lineno">  430</span><span class="comment">   *        behavior is what you&#39;re after -- and either don&#39;t need additional signal handling or are OK with using</span></div>
<div class="line"><a id="l00431" name="l00431"></a><span class="lineno">  431</span><span class="comment">   *        `signal_set` for it -- then setting this to `true` is a good option.</span></div>
<div class="line"><a id="l00432" name="l00432"></a><span class="lineno">  432</span><span class="comment">   */</span></div>
<div class="line"><a id="l00433" name="l00433"></a><span class="lineno">  433</span>  <span class="keyword">explicit</span> <a class="code hl_function" href="classflow_1_1log_1_1Async__file__logger.html#aec2b1796c81b020cacea493e21e19562">Async_file_logger</a>(<a class="code hl_class" href="classflow_1_1log_1_1Logger.html">Logger</a>* backup_logger_ptr,</div>
<div class="line"><a id="l00434" name="l00434"></a><span class="lineno">  434</span>                             <a class="code hl_class" href="classflow_1_1log_1_1Config.html">Config</a>* config, <span class="keyword">const</span> fs::path&amp; log_path,</div>
<div class="line"><a id="l00435" name="l00435"></a><span class="lineno">  435</span>                             <span class="keywordtype">bool</span> capture_rotate_signals_internally);</div>
<div class="line"><a id="l00436" name="l00436"></a><span class="lineno">  436</span><span class="comment"></span> </div>
<div class="line"><a id="l00437" name="l00437"></a><span class="lineno">  437</span><span class="comment">  /// Flushes out anything buffered, returns resources/closes output file(s); then returns.</span></div>
<div class="line"><a id="l00438" name="l00438"></a><span class="lineno">  438</span><span class="comment"></span>  <a class="code hl_function" href="classflow_1_1log_1_1Async__file__logger.html#ae48ec685cc9951a37bb670dd92fe1f4e">~Async_file_logger</a>() <span class="keyword">override</span>;</div>
<div class="line"><a id="l00439" name="l00439"></a><span class="lineno">  439</span> </div>
<div class="line"><a id="l00440" name="l00440"></a><span class="lineno">  440</span>  <span class="comment">// Methods.</span></div>
<div class="line"><a id="l00441" name="l00441"></a><span class="lineno">  441</span><span class="comment"></span> </div>
<div class="line"><a id="l00442" name="l00442"></a><span class="lineno">  442</span><span class="comment">  /**</span></div>
<div class="line"><a id="l00443" name="l00443"></a><span class="lineno">  443</span><span class="comment">   * Implements interface method by returning `true` if the severity and component (which is allowed to be null)</span></div>
<div class="line"><a id="l00444" name="l00444"></a><span class="lineno">  444</span><span class="comment">   * indicate it should; and if so potentially applies the throttling algorithm&#39;s result as well.</span></div>
<div class="line"><a id="l00445" name="l00445"></a><span class="lineno">  445</span><span class="comment">   * As of this writing not thread-safe against changes to `*m_config` (but thread-safe agains throttling_cfg()</span></div>
<div class="line"><a id="l00446" name="l00446"></a><span class="lineno">  446</span><span class="comment">   * mutator).</span></div>
<div class="line"><a id="l00447" name="l00447"></a><span class="lineno">  447</span><span class="comment">   *</span></div>
<div class="line"><a id="l00448" name="l00448"></a><span class="lineno">  448</span><span class="comment">   * Throttling comes into play if and only if: 1, `sev` and `component` indicate</span></div>
<div class="line"><a id="l00449" name="l00449"></a><span class="lineno">  449</span><span class="comment">   * should_log() should return `true` in the first place; and 2, `throttling_active() == true`.  In that case</span></div>
<div class="line"><a id="l00450" name="l00450"></a><span class="lineno">  450</span><span class="comment">   * the throttling alogorithm&#39;s current output (Throttling versus Not-Throttling state) is consulted to determine</span></div>
<div class="line"><a id="l00451" name="l00451"></a><span class="lineno">  451</span><span class="comment">   * whether to return `true` or `false`.  (See Throttling section of class doc header.)</span></div>
<div class="line"><a id="l00452" name="l00452"></a><span class="lineno">  452</span><span class="comment">   *</span></div>
<div class="line"><a id="l00453" name="l00453"></a><span class="lineno">  453</span><span class="comment">   * @param sev</span></div>
<div class="line"><a id="l00454" name="l00454"></a><span class="lineno">  454</span><span class="comment">   *        Severity of the message.</span></div>
<div class="line"><a id="l00455" name="l00455"></a><span class="lineno">  455</span><span class="comment">   * @param component</span></div>
<div class="line"><a id="l00456" name="l00456"></a><span class="lineno">  456</span><span class="comment">   *        Component of the message.  Reminder: `component.empty() == true` is allowed.</span></div>
<div class="line"><a id="l00457" name="l00457"></a><span class="lineno">  457</span><span class="comment">   * @return See above.</span></div>
<div class="line"><a id="l00458" name="l00458"></a><span class="lineno">  458</span><span class="comment">   */</span></div>
<div class="line"><a id="l00459" name="l00459"></a><span class="lineno">  459</span>  <span class="keywordtype">bool</span> <a class="code hl_function" href="classflow_1_1log_1_1Async__file__logger.html#ad139ac22e5953e52e03648860a15e3fd">should_log</a>(<a class="code hl_enumeration" href="namespaceflow_1_1log.html#a5c602384e6fe9d7642740ac2fae4ad04">Sev</a> sev, <span class="keyword">const</span> <a class="code hl_class" href="classflow_1_1log_1_1Component.html">Component</a>&amp; component) <span class="keyword">const override</span>;</div>
<div class="line"><a id="l00460" name="l00460"></a><span class="lineno">  460</span><span class="comment"></span> </div>
<div class="line"><a id="l00461" name="l00461"></a><span class="lineno">  461</span><span class="comment">  /**</span></div>
<div class="line"><a id="l00462" name="l00462"></a><span class="lineno">  462</span><span class="comment">   * Implements interface method by returning `true`, indicating that this Logger may need the contents of</span></div>
<div class="line"><a id="l00463" name="l00463"></a><span class="lineno">  463</span><span class="comment">   * `*metadata` and `msg` passed to do_log() even after that method returns.</span></div>
<div class="line"><a id="l00464" name="l00464"></a><span class="lineno">  464</span><span class="comment">   *</span></div>
<div class="line"><a id="l00465" name="l00465"></a><span class="lineno">  465</span><span class="comment">   * @return See above.</span></div>
<div class="line"><a id="l00466" name="l00466"></a><span class="lineno">  466</span><span class="comment">   */</span></div>
<div class="line"><a id="l00467" name="l00467"></a><span class="lineno">  467</span>  <span class="keywordtype">bool</span> <a class="code hl_function" href="classflow_1_1log_1_1Async__file__logger.html#afd773546633aec017f2041feb3a75dd3">logs_asynchronously</a>() <span class="keyword">const override</span>;</div>
<div class="line"><a id="l00468" name="l00468"></a><span class="lineno">  468</span><span class="comment"></span> </div>
<div class="line"><a id="l00469" name="l00469"></a><span class="lineno">  469</span><span class="comment">  /**</span></div>
<div class="line"><a id="l00470" name="l00470"></a><span class="lineno">  470</span><span class="comment">   * Implements interface method by asynchronously logging the message and some subset of the metadata in a fashion</span></div>
<div class="line"><a id="l00471" name="l00471"></a><span class="lineno">  471</span><span class="comment">   * controlled by #m_config.</span></div>
<div class="line"><a id="l00472" name="l00472"></a><span class="lineno">  472</span><span class="comment">   *</span></div>
<div class="line"><a id="l00473" name="l00473"></a><span class="lineno">  473</span><span class="comment">   * @param metadata</span></div>
<div class="line"><a id="l00474" name="l00474"></a><span class="lineno">  474</span><span class="comment">   *        All information to potentially log in addition to `msg`.</span></div>
<div class="line"><a id="l00475" name="l00475"></a><span class="lineno">  475</span><span class="comment">   * @param msg</span></div>
<div class="line"><a id="l00476" name="l00476"></a><span class="lineno">  476</span><span class="comment">   *        The message.</span></div>
<div class="line"><a id="l00477" name="l00477"></a><span class="lineno">  477</span><span class="comment">   */</span></div>
<div class="line"><a id="l00478" name="l00478"></a><span class="lineno">  478</span>  <span class="keywordtype">void</span> <a class="code hl_function" href="classflow_1_1log_1_1Async__file__logger.html#aa557c0f55c1044161acc8fb54c115a3e">do_log</a>(<a class="code hl_struct" href="structflow_1_1log_1_1Msg__metadata.html">Msg_metadata</a>* metadata, <a class="code hl_typedef" href="namespaceflow_1_1util.html#ae4dc52186797094b3040379ff19124c9">util::String_view</a> msg) <span class="keyword">override</span>;</div>
<div class="line"><a id="l00479" name="l00479"></a><span class="lineno">  479</span><span class="comment"></span> </div>
<div class="line"><a id="l00480" name="l00480"></a><span class="lineno">  480</span><span class="comment">  /**</span></div>
<div class="line"><a id="l00481" name="l00481"></a><span class="lineno">  481</span><span class="comment">   * Causes the log at the file-system path to be flushed/closed (if needed) and</span></div>
<div class="line"><a id="l00482" name="l00482"></a><span class="lineno">  482</span><span class="comment">   * re-opened; this will happen as soon as possible but may occur asynchronously after this method exits, unless</span></div>
<div class="line"><a id="l00483" name="l00483"></a><span class="lineno">  483</span><span class="comment">   * directed otherwise via `async` argument.</span></div>
<div class="line"><a id="l00484" name="l00484"></a><span class="lineno">  484</span><span class="comment">   *</span></div>
<div class="line"><a id="l00485" name="l00485"></a><span class="lineno">  485</span><span class="comment">   * ### Uses ###</span></div>
<div class="line"><a id="l00486" name="l00486"></a><span class="lineno">  486</span><span class="comment">   * Flushing: `log_flush_and_reopen(false)` is a reasonable and safe way to flush anything buffered in memory to the</span></div>
<div class="line"><a id="l00487" name="l00487"></a><span class="lineno">  487</span><span class="comment">   * file.  Naturally, for performance, it should not be done frequently.  For example this might be useful in the</span></div>
<div class="line"><a id="l00488" name="l00488"></a><span class="lineno">  488</span><span class="comment">   * event of an abnormal termination (`abort()`, etc.), in the signal handler before exiting program.</span></div>
<div class="line"><a id="l00489" name="l00489"></a><span class="lineno">  489</span><span class="comment">   *</span></div>
<div class="line"><a id="l00490" name="l00490"></a><span class="lineno">  490</span><span class="comment">   * Rotation: `log_flush_and_reopen(true)` is useful for rotation purposes; however, you need not do this manually if</span></div>
<div class="line"><a id="l00491" name="l00491"></a><span class="lineno">  491</span><span class="comment">   * you decided to (properly) use the `capture_rotate_signals_internally == true` option in Async_file_logger</span></div>
<div class="line"><a id="l00492" name="l00492"></a><span class="lineno">  492</span><span class="comment">   * constructor; the procedure will occur on receiving the proper signal automatically.</span></div>
<div class="line"><a id="l00493" name="l00493"></a><span class="lineno">  493</span><span class="comment">   *</span></div>
<div class="line"><a id="l00494" name="l00494"></a><span class="lineno">  494</span><span class="comment">   * @todo `Async_file_logger::log_flush_and_reopen(true)` is great for flushing, such as in an abort-signal handler,</span></div>
<div class="line"><a id="l00495" name="l00495"></a><span class="lineno">  495</span><span class="comment">   * but providing just the flushing part without the reopening might be useful.  At the moment we&#39;ve left it</span></div>
<div class="line"><a id="l00496" name="l00496"></a><span class="lineno">  496</span><span class="comment">   * this way, due to the vague feeling that closing the file upon flushing it is somehow more final and thus safer</span></div>
<div class="line"><a id="l00497" name="l00497"></a><span class="lineno">  497</span><span class="comment">   * (in terms of accomplishing its goal) in an abort-signal scenario.  Feelings aren&#39;t very scientific though.</span></div>
<div class="line"><a id="l00498" name="l00498"></a><span class="lineno">  498</span><span class="comment">   *</span></div>
<div class="line"><a id="l00499" name="l00499"></a><span class="lineno">  499</span><span class="comment">   * @param async</span></div>
<div class="line"><a id="l00500" name="l00500"></a><span class="lineno">  500</span><span class="comment">   *        If `true`, the operation will execute ASAP but asynchronously, the method exiting immediately;</span></div>
<div class="line"><a id="l00501" name="l00501"></a><span class="lineno">  501</span><span class="comment">   *        else it will complete fully before this method returns.</span></div>
<div class="line"><a id="l00502" name="l00502"></a><span class="lineno">  502</span><span class="comment">   */</span></div>
<div class="line"><a id="l00503" name="l00503"></a><span class="lineno">  503</span>  <span class="keywordtype">void</span> <a class="code hl_function" href="classflow_1_1log_1_1Async__file__logger.html#aaaf956d63042cbc0800680996adabfa2">log_flush_and_reopen</a>(<span class="keywordtype">bool</span> async = <span class="keyword">true</span>);</div>
<div class="line"><a id="l00504" name="l00504"></a><span class="lineno">  504</span><span class="comment"></span> </div>
<div class="line"><a id="l00505" name="l00505"></a><span class="lineno">  505</span><span class="comment">  /**</span></div>
<div class="line"><a id="l00506" name="l00506"></a><span class="lineno">  506</span><span class="comment">   * Accessor returning a copy of the current set of throttling knobs.  Please see Async_file_logger doc header</span></div>
<div class="line"><a id="l00507" name="l00507"></a><span class="lineno">  507</span><span class="comment">   * Throttling section for description of their meanings in the algorithm.</span></div>
<div class="line"><a id="l00508" name="l00508"></a><span class="lineno">  508</span><span class="comment">   *</span></div>
<div class="line"><a id="l00509" name="l00509"></a><span class="lineno">  509</span><span class="comment">   * @see throttling_active() also.</span></div>
<div class="line"><a id="l00510" name="l00510"></a><span class="lineno">  510</span><span class="comment">   *</span></div>
<div class="line"><a id="l00511" name="l00511"></a><span class="lineno">  511</span><span class="comment">   * @return The current knobs controlling the behavior of the algorithm that determines</span></div>
<div class="line"><a id="l00512" name="l00512"></a><span class="lineno">  512</span><span class="comment">   *         Throttling versus Not-Throttling state.</span></div>
<div class="line"><a id="l00513" name="l00513"></a><span class="lineno">  513</span><span class="comment">   *         If throttling_cfg() mutator is never called, then the values therein will be some valid defaults.</span></div>
<div class="line"><a id="l00514" name="l00514"></a><span class="lineno">  514</span><span class="comment">   */</span></div>
<div class="line"><a id="l00515" name="l00515"></a><span class="lineno">  515</span>  <a class="code hl_struct" href="structflow_1_1log_1_1Async__file__logger_1_1Throttling__cfg.html">Throttling_cfg</a> <a class="code hl_function" href="classflow_1_1log_1_1Async__file__logger.html#ac2080e8abfc2cd9580c84626ae205010">throttling_cfg</a>() <span class="keyword">const</span>;</div>
<div class="line"><a id="l00516" name="l00516"></a><span class="lineno">  516</span><span class="comment"></span> </div>
<div class="line"><a id="l00517" name="l00517"></a><span class="lineno">  517</span><span class="comment">  /**</span></div>
<div class="line"><a id="l00518" name="l00518"></a><span class="lineno">  518</span><span class="comment">   * Whether the throttling feature is currently in effect.  That is: can the throttling computations actually</span></div>
<div class="line"><a id="l00519" name="l00519"></a><span class="lineno">  519</span><span class="comment">   * affect should_log() output?  (It is *not* about whether log lines are actually being rejected due to throttling</span></div>
<div class="line"><a id="l00520" name="l00520"></a><span class="lineno">  520</span><span class="comment">   * right now.)  Please see Async_file_logger doc header Throttling section for more info.</span></div>
<div class="line"><a id="l00521" name="l00521"></a><span class="lineno">  521</span><span class="comment">   *</span></div>
<div class="line"><a id="l00522" name="l00522"></a><span class="lineno">  522</span><span class="comment">   * If `true` should_log() will potentially consider Throttling versus Not-Throttling state; else it will ignore it.</span></div>
<div class="line"><a id="l00523" name="l00523"></a><span class="lineno">  523</span><span class="comment">   * If throttling_cfg() mutator is never called, then this shall be `false` (feature inactive by default).</span></div>
<div class="line"><a id="l00524" name="l00524"></a><span class="lineno">  524</span><span class="comment">   *</span></div>
<div class="line"><a id="l00525" name="l00525"></a><span class="lineno">  525</span><span class="comment">   * @see throttling_cfg() accessor also.</span></div>
<div class="line"><a id="l00526" name="l00526"></a><span class="lineno">  526</span><span class="comment">   *</span></div>
<div class="line"><a id="l00527" name="l00527"></a><span class="lineno">  527</span><span class="comment">   * @return See above.</span></div>
<div class="line"><a id="l00528" name="l00528"></a><span class="lineno">  528</span><span class="comment">   */</span></div>
<div class="line"><a id="l00529" name="l00529"></a><span class="lineno">  529</span>  <span class="keywordtype">bool</span> <a class="code hl_function" href="classflow_1_1log_1_1Async__file__logger.html#a83cff0d6857a8295e41f90d5e9cab711">throttling_active</a>() <span class="keyword">const</span>;</div>
<div class="line"><a id="l00530" name="l00530"></a><span class="lineno">  530</span><span class="comment"></span> </div>
<div class="line"><a id="l00531" name="l00531"></a><span class="lineno">  531</span><span class="comment">  /**</span></div>
<div class="line"><a id="l00532" name="l00532"></a><span class="lineno">  532</span><span class="comment">   * Mutator that sets the throttling knobs.  Please see Async_file_logger doc header</span></div>
<div class="line"><a id="l00533" name="l00533"></a><span class="lineno">  533</span><span class="comment">   * Throttling section for description of their meanings in the algorithm.</span></div>
<div class="line"><a id="l00534" name="l00534"></a><span class="lineno">  534</span><span class="comment">   *</span></div>
<div class="line"><a id="l00535" name="l00535"></a><span class="lineno">  535</span><span class="comment">   * ### Thread safety ###</span></div>
<div class="line"><a id="l00536" name="l00536"></a><span class="lineno">  536</span><span class="comment">   * It is okay to call concurrently with any other method on the same `*this`, except it must not be called</span></div>
<div class="line"><a id="l00537" name="l00537"></a><span class="lineno">  537</span><span class="comment">   * concurrently with itself.</span></div>
<div class="line"><a id="l00538" name="l00538"></a><span class="lineno">  538</span><span class="comment">   *</span></div>
<div class="line"><a id="l00539" name="l00539"></a><span class="lineno">  539</span><span class="comment">   * @param active</span></div>
<div class="line"><a id="l00540" name="l00540"></a><span class="lineno">  540</span><span class="comment">   *        Whether the feature shall be in effect (if should_log() will</span></div>
<div class="line"><a id="l00541" name="l00541"></a><span class="lineno">  541</span><span class="comment">   *        potentially consider Throttling versus Not-Throttling state; else it will ignore it).</span></div>
<div class="line"><a id="l00542" name="l00542"></a><span class="lineno">  542</span><span class="comment">   * @param cfg</span></div>
<div class="line"><a id="l00543" name="l00543"></a><span class="lineno">  543</span><span class="comment">   *        The new values for knobs controlling the behavior of the algorithm that determines</span></div>
<div class="line"><a id="l00544" name="l00544"></a><span class="lineno">  544</span><span class="comment">   *        Throttling versus Not-Throttling state.</span></div>
<div class="line"><a id="l00545" name="l00545"></a><span class="lineno">  545</span><span class="comment">   */</span></div>
<div class="line"><a id="l00546" name="l00546"></a><span class="lineno">  546</span>  <span class="keywordtype">void</span> <a class="code hl_function" href="classflow_1_1log_1_1Async__file__logger.html#ac2080e8abfc2cd9580c84626ae205010">throttling_cfg</a>(<span class="keywordtype">bool</span> active, <span class="keyword">const</span> <a class="code hl_struct" href="structflow_1_1log_1_1Async__file__logger_1_1Throttling__cfg.html">Throttling_cfg</a>&amp; cfg);</div>
<div class="line"><a id="l00547" name="l00547"></a><span class="lineno">  547</span> </div>
<div class="line"><a id="l00548" name="l00548"></a><span class="lineno">  548</span>  <span class="comment">// Data.  (Public!)</span></div>
<div class="line"><a id="l00549" name="l00549"></a><span class="lineno">  549</span><span class="comment"></span> </div>
<div class="line"><a id="l00550" name="l00550"></a><span class="lineno">  550</span><span class="comment">  /**</span></div>
<div class="line"><a id="l00551" name="l00551"></a><span class="lineno">  551</span><span class="comment">   * Reference to the config object passed to constructor.  Note that object is mutable; see notes on thread safety.</span></div>
<div class="line"><a id="l00552" name="l00552"></a><span class="lineno">  552</span><span class="comment">   *</span></div>
<div class="line"><a id="l00553" name="l00553"></a><span class="lineno">  553</span><span class="comment">   * @internal</span></div>
<div class="line"><a id="l00554" name="l00554"></a><span class="lineno">  554</span><span class="comment">   * ### Rationale ###</span></div>
<div class="line"><a id="l00555" name="l00555"></a><span class="lineno">  555</span><span class="comment">   * This can be (and is but not exclusively) exclusively stored in `m_serial_logger-&gt;m_config`; it is stored here also</span></div>
<div class="line"><a id="l00556" name="l00556"></a><span class="lineno">  556</span><span class="comment">   * for `public` access to the user.  It&#39;s a pointer in any case.</span></div>
<div class="line"><a id="l00557" name="l00557"></a><span class="lineno">  557</span><span class="comment">   */</span></div>
<div class="line"><a id="l00558" name="l00558"></a><span class="lineno"><a class="line" href="classflow_1_1log_1_1Async__file__logger.html#a4b6dcf5c791e32c517c41c935fba29a4">  558</a></span>  <a class="code hl_class" href="classflow_1_1log_1_1Config.html">Config</a>* <span class="keyword">const</span> <a class="code hl_variable" href="classflow_1_1log_1_1Async__file__logger.html#a4b6dcf5c791e32c517c41c935fba29a4">m_config</a>;</div>
<div class="line"><a id="l00559" name="l00559"></a><span class="lineno">  559</span> </div>
<div class="line"><a id="l00560" name="l00560"></a><span class="lineno">  560</span><span class="keyword">private</span>:</div>
<div class="line"><a id="l00561" name="l00561"></a><span class="lineno">  561</span>  <span class="comment">// Types.</span></div>
<div class="line"><a id="l00562" name="l00562"></a><span class="lineno">  562</span><span class="comment"></span> </div>
<div class="line"><a id="l00563" name="l00563"></a><span class="lineno">  563</span><span class="comment">  /// Short-hand for #m_throttling_mutex type.</span></div>
<div class="line"><a id="l00564" name="l00564"></a><span class="lineno"><a class="line" href="classflow_1_1log_1_1Async__file__logger.html#a2f21285253ab0f9a81cf991f99ce6549">  564</a></span><span class="comment"></span>  <span class="keyword">using </span><a class="code hl_typedef" href="classflow_1_1log_1_1Async__file__logger.html#a2f21285253ab0f9a81cf991f99ce6549">Mutex</a> = <a class="code hl_typedef" href="namespaceflow_1_1util.html#add6ade273326f27eaf9bfd170a909626">flow::util::Mutex_non_recursive</a>;</div>
<div class="line"><a id="l00565" name="l00565"></a><span class="lineno">  565</span><span class="comment"></span> </div>
<div class="line"><a id="l00566" name="l00566"></a><span class="lineno">  566</span><span class="comment">  /// Short-hand for #Mutex lock.</span></div>
<div class="line"><a id="l00567" name="l00567"></a><span class="lineno"><a class="line" href="classflow_1_1log_1_1Async__file__logger.html#a10757ede565842d0faebf50bc1424610">  567</a></span><span class="comment"></span>  <span class="keyword">using </span><a class="code hl_typedef" href="classflow_1_1log_1_1Async__file__logger.html#a10757ede565842d0faebf50bc1424610">Lock_guard</a> = <a class="code hl_typedef" href="namespaceflow_1_1util.html#a5d2247b715da63e4b960909561b90ae7">flow::util::Lock_guard&lt;Mutex&gt;</a>;</div>
<div class="line"><a id="l00568" name="l00568"></a><span class="lineno">  568</span><span class="comment"></span> </div>
<div class="line"><a id="l00569" name="l00569"></a><span class="lineno">  569</span><span class="comment">  /// Short-hand for a signal set.</span></div>
<div class="line"><a id="l00570" name="l00570"></a><span class="lineno"><a class="line" href="classflow_1_1log_1_1Async__file__logger.html#aa452be34d366b80024eaed98d47b987f">  570</a></span><span class="comment"></span>  <span class="keyword">using </span><a class="code hl_typedef" href="classflow_1_1log_1_1Async__file__logger.html#aa452be34d366b80024eaed98d47b987f">Signal_set</a> = boost::asio::signal_set;</div>
<div class="line"><a id="l00571" name="l00571"></a><span class="lineno">  571</span><span class="comment"></span> </div>
<div class="line"><a id="l00572" name="l00572"></a><span class="lineno">  572</span><span class="comment">  /**</span></div>
<div class="line"><a id="l00573" name="l00573"></a><span class="lineno">  573</span><span class="comment">   * In addition to the task object (function) itself, these are the data placed onto the queue of `m_async_worker`</span></div>
<div class="line"><a id="l00574" name="l00574"></a><span class="lineno">  574</span><span class="comment">   * tasks for a particular `do_log()` call, to be used by that task and then freed immediately upon logging of the</span></div>
<div class="line"><a id="l00575" name="l00575"></a><span class="lineno">  575</span><span class="comment">   * message to file.</span></div>
<div class="line"><a id="l00576" name="l00576"></a><span class="lineno">  576</span><span class="comment">   *</span></div>
<div class="line"><a id="l00577" name="l00577"></a><span class="lineno">  577</span><span class="comment">   * @see mem_cost().</span></div>
<div class="line"><a id="l00578" name="l00578"></a><span class="lineno">  578</span><span class="comment">   *</span></div>
<div class="line"><a id="l00579" name="l00579"></a><span class="lineno">  579</span><span class="comment">   * ### Rationale/details ###</span></div>
<div class="line"><a id="l00580" name="l00580"></a><span class="lineno">  580</span><span class="comment">   * The object is movable which is important.  It is also copyable but only because, as of this writing, C++17</span></div>
<div class="line"><a id="l00581" name="l00581"></a><span class="lineno">  581</span><span class="comment">   * requires captures by value to be copyable (in order to compile), even though this is *not executed at runtime*,</span></div>
<div class="line"><a id="l00582" name="l00582"></a><span class="lineno">  582</span><span class="comment">   * unless one actually needs to make a copy of the function object (which we avoid like the plague).</span></div>
<div class="line"><a id="l00583" name="l00583"></a><span class="lineno">  583</span><span class="comment">   *</span></div>
<div class="line"><a id="l00584" name="l00584"></a><span class="lineno">  584</span><span class="comment">   * We try hard -- harder than in most situations -- to keep the memory footprint of this thing as small as possible,</span></div>
<div class="line"><a id="l00585" name="l00585"></a><span class="lineno">  585</span><span class="comment">   * right down to even avoiding a `shared_ptr`, when a raw or `unique_ptr` is enough; and not storing the result</span></div>
<div class="line"><a id="l00586" name="l00586"></a><span class="lineno">  586</span><span class="comment">   * of mem_cost() (but rather recomputing it inside the `m_async_worker` task).  That is because of the same memory</span></div>
<div class="line"><a id="l00587" name="l00587"></a><span class="lineno">  587</span><span class="comment">   * use potential problem with which the throttling feature (see Async_file_logger class doc header) grapples.</span></div>
<div class="line"><a id="l00588" name="l00588"></a><span class="lineno">  588</span><span class="comment">   *</span></div>
<div class="line"><a id="l00589" name="l00589"></a><span class="lineno">  589</span><span class="comment">   * Ideally each item stored here has RAII semantics, meaning once the object is destroyed, the stuff referred-to</span></div>
<div class="line"><a id="l00590" name="l00590"></a><span class="lineno">  590</span><span class="comment">   * therein is destroyed.  However you&#39;ll notice this is not the case at least for #m_metadata and</span></div>
<div class="line"><a id="l00591" name="l00591"></a><span class="lineno">  591</span><span class="comment">   * for #m_msg_copy.  Therefore the function body (the `m_async_worker` task for this Log_request) must manually</span></div>
<div class="line"><a id="l00592" name="l00592"></a><span class="lineno">  592</span><span class="comment">   * `delete` these objects from the heap.  Moreover, if the lambda were to never run (e.g., if we destroyed or</span></div>
<div class="line"><a id="l00593" name="l00593"></a><span class="lineno">  593</span><span class="comment">   * stopped `m_async_worker` while tasks are still enqueued), those objects would get leaked.  (As of this writing</span></div>
<div class="line"><a id="l00594" name="l00594"></a><span class="lineno">  594</span><span class="comment">   * we always flush the queue in Async_file_logger dtor for this and another reason.)</span></div>
<div class="line"><a id="l00595" name="l00595"></a><span class="lineno">  595</span><span class="comment">   *</span></div>
<div class="line"><a id="l00596" name="l00596"></a><span class="lineno">  596</span><span class="comment">   * So why not just use `unique_ptr` then?  The reason is above: they&#39;re not copyable, and we need it to be,</span></div>
<div class="line"><a id="l00597" name="l00597"></a><span class="lineno">  597</span><span class="comment">   * as otherwise C++17 won&#39;t let Log_request be value-captured in lambda.  One can use `shared_ptr`; this is elegant,</span></div>
<div class="line"><a id="l00598" name="l00598"></a><span class="lineno">  598</span><span class="comment">   * but at this point we&#39;re specifically trying to reduce the RAM use to the bare minimum, so we avoid even</span></div>
<div class="line"><a id="l00599" name="l00599"></a><span class="lineno">  599</span><span class="comment">   * the tiny control block size of `shared_ptr`.  For #m_msg_copy one could have used `std::string` or util::Basic_blob</span></div>
<div class="line"><a id="l00600" name="l00600"></a><span class="lineno">  600</span><span class="comment">   * or `std::vector`, but they all have some extra members we do not need (size on top of capacity; `Basic_blob`</span></div>
<div class="line"><a id="l00601" name="l00601"></a><span class="lineno">  601</span><span class="comment">   * also has `m_start`).  (util::Basic_blob doc header as of this writing has a to-do to implement a</span></div>
<div class="line"><a id="l00602" name="l00602"></a><span class="lineno">  602</span><span class="comment">   * `Tight_blob` class with just the pointer and capacity, no extras; so that would have been useful.)  Even</span></div>
<div class="line"><a id="l00603" name="l00603"></a><span class="lineno">  603</span><span class="comment">   * with those options, that would&#39;ve still left #m_metadata.  One could write little wrapper classes for both</span></div>
<div class="line"><a id="l00604" name="l00604"></a><span class="lineno">  604</span><span class="comment">   * the string blob #m_msg_copy and/or Msg_metadata #m_metadata, and that did work.  Simply put, however, storing the</span></div>
<div class="line"><a id="l00605" name="l00605"></a><span class="lineno">  605</span><span class="comment">   * rare raw pointers and then explicitly `delete`ing them in one spot is just much less boiler-plate.</span></div>
<div class="line"><a id="l00606" name="l00606"></a><span class="lineno">  606</span><span class="comment">   *</span></div>
<div class="line"><a id="l00607" name="l00607"></a><span class="lineno">  607</span><span class="comment">   * @warning Just be careful with maintenance.  Tests should indeed try to force the above leak and use sanitizers</span></div>
<div class="line"><a id="l00608" name="l00608"></a><span class="lineno">  608</span><span class="comment">   * (etc.) to ensure it is avoided.</span></div>
<div class="line"><a id="l00609" name="l00609"></a><span class="lineno">  609</span><span class="comment">   */</span></div>
<div class="line"><a id="l00610" name="l00610"></a><span class="lineno"><a class="line" href="structflow_1_1log_1_1Async__file__logger_1_1Log__request.html">  610</a></span>  <span class="keyword">struct </span><a class="code hl_struct" href="structflow_1_1log_1_1Async__file__logger_1_1Log__request.html">Log_request</a></div>
<div class="line"><a id="l00611" name="l00611"></a><span class="lineno">  611</span>  {</div>
<div class="line"><a id="l00612" name="l00612"></a><span class="lineno">  612</span>    <span class="comment">// Data.</span></div>
<div class="line"><a id="l00613" name="l00613"></a><span class="lineno">  613</span><span class="comment"></span> </div>
<div class="line"><a id="l00614" name="l00614"></a><span class="lineno">  614</span><span class="comment">    /// Pointer to array of characters comprising a copy of `msg` passed to `do_log()`.  We must `delete[]` it.</span></div>
<div class="line"><a id="l00615" name="l00615"></a><span class="lineno"><a class="line" href="structflow_1_1log_1_1Async__file__logger_1_1Log__request.html#a82a13a6d045612578dad42a82de36202">  615</a></span><span class="comment"></span>    <span class="keywordtype">char</span>* <a class="code hl_variable" href="structflow_1_1log_1_1Async__file__logger_1_1Log__request.html#a82a13a6d045612578dad42a82de36202">m_msg_copy</a>;</div>
<div class="line"><a id="l00616" name="l00616"></a><span class="lineno">  616</span><span class="comment"></span> </div>
<div class="line"><a id="l00617" name="l00617"></a><span class="lineno">  617</span><span class="comment">    /// Number of characters in #m_msg_copy pointee string.</span></div>
<div class="line"><a id="l00618" name="l00618"></a><span class="lineno"><a class="line" href="structflow_1_1log_1_1Async__file__logger_1_1Log__request.html#a43b7a817420a80d955e4acfd0ec10f45">  618</a></span><span class="comment"></span>    <span class="keywordtype">size_t</span> <a class="code hl_variable" href="structflow_1_1log_1_1Async__file__logger_1_1Log__request.html#a43b7a817420a80d955e4acfd0ec10f45">m_msg_size</a>;</div>
<div class="line"><a id="l00619" name="l00619"></a><span class="lineno">  619</span><span class="comment"></span> </div>
<div class="line"><a id="l00620" name="l00620"></a><span class="lineno">  620</span><span class="comment">    /// Pointer to array of characters comprising a copy of `msg` passed to `do_log()`.  We must `delete` it.</span></div>
<div class="line"><a id="l00621" name="l00621"></a><span class="lineno"><a class="line" href="structflow_1_1log_1_1Async__file__logger_1_1Log__request.html#a7215d35008420d5c3357df1b06761d64">  621</a></span><span class="comment"></span>    <a class="code hl_struct" href="structflow_1_1log_1_1Msg__metadata.html">Msg_metadata</a>* <a class="code hl_variable" href="structflow_1_1log_1_1Async__file__logger_1_1Log__request.html#a7215d35008420d5c3357df1b06761d64">m_metadata</a>;</div>
<div class="line"><a id="l00622" name="l00622"></a><span class="lineno">  622</span><span class="comment"></span> </div>
<div class="line"><a id="l00623" name="l00623"></a><span class="lineno">  623</span><span class="comment">    /**</span></div>
<div class="line"><a id="l00624" name="l00624"></a><span class="lineno">  624</span><span class="comment">     * Whether this log request was such that its memory footprint (`mem_cost()`) pushed `m_pending_logs_sz` from</span></div>
<div class="line"><a id="l00625" name="l00625"></a><span class="lineno">  625</span><span class="comment">     * `&lt; m_throttling_cfg.m_hi_limit` to `&gt;= m_throttling_cfg.m_hi_limit` for the first time since it was last</span></div>
<div class="line"><a id="l00626" name="l00626"></a><span class="lineno">  626</span><span class="comment">     * equal to zero.</span></div>
<div class="line"><a id="l00627" name="l00627"></a><span class="lineno">  627</span><span class="comment">     */</span></div>
<div class="line"><a id="l00628" name="l00628"></a><span class="lineno"><a class="line" href="structflow_1_1log_1_1Async__file__logger_1_1Log__request.html#aee7f652b0e17e39d0afdb721bc956cf7">  628</a></span>    <span class="keywordtype">bool</span> <a class="code hl_variable" href="structflow_1_1log_1_1Async__file__logger_1_1Log__request.html#aee7f652b0e17e39d0afdb721bc956cf7">m_throttling_begins</a>;</div>
<div class="line"><a id="l00629" name="l00629"></a><span class="lineno">  629</span>  }; <span class="comment">// struct Log_request</span></div>
<div class="line"><a id="l00630" name="l00630"></a><span class="lineno">  630</span> </div>
<div class="line"><a id="l00631" name="l00631"></a><span class="lineno">  631</span>  <span class="comment">// Methods.</span></div>
<div class="line"><a id="l00632" name="l00632"></a><span class="lineno">  632</span><span class="comment"></span> </div>
<div class="line"><a id="l00633" name="l00633"></a><span class="lineno">  633</span><span class="comment">  /**</span></div>
<div class="line"><a id="l00634" name="l00634"></a><span class="lineno">  634</span><span class="comment">   * SIGHUP/equivalent handler for the optional feature `capture_rotate_signals_internally` in constructor.</span></div>
<div class="line"><a id="l00635" name="l00635"></a><span class="lineno">  635</span><span class="comment">   * Assuming no error, executes `m_serial_logger-&gt;log_flush_and_reopen()` and then again waits for the next such</span></div>
<div class="line"><a id="l00636" name="l00636"></a><span class="lineno">  636</span><span class="comment">   * signal.</span></div>
<div class="line"><a id="l00637" name="l00637"></a><span class="lineno">  637</span><span class="comment">   *</span></div>
<div class="line"><a id="l00638" name="l00638"></a><span class="lineno">  638</span><span class="comment">   * @param sys_err_code</span></div>
<div class="line"><a id="l00639" name="l00639"></a><span class="lineno">  639</span><span class="comment">   *        The code from boost.asio.  Anything outside of `operation_aborted` is very strange.</span></div>
<div class="line"><a id="l00640" name="l00640"></a><span class="lineno">  640</span><span class="comment">   * @param sig_number</span></div>
<div class="line"><a id="l00641" name="l00641"></a><span class="lineno">  641</span><span class="comment">   *        Should be SIGHUP/equivalent, as we only wait for those signal(s).</span></div>
<div class="line"><a id="l00642" name="l00642"></a><span class="lineno">  642</span><span class="comment">   */</span></div>
<div class="line"><a id="l00643" name="l00643"></a><span class="lineno">  643</span>  <span class="keywordtype">void</span> <a class="code hl_function" href="classflow_1_1log_1_1Async__file__logger.html#a541843c3b49c59a70aad70d8ab984188">on_rotate_signal</a>(<span class="keyword">const</span> <a class="code hl_typedef" href="namespaceflow.html#a29eaaa9d0fac4ce87d8b969222dbed09">Error_code</a>&amp; sys_err_code, <span class="keywordtype">int</span> sig_number);</div>
<div class="line"><a id="l00644" name="l00644"></a><span class="lineno">  644</span><span class="comment"></span> </div>
<div class="line"><a id="l00645" name="l00645"></a><span class="lineno">  645</span><span class="comment">  /**</span></div>
<div class="line"><a id="l00646" name="l00646"></a><span class="lineno">  646</span><span class="comment">   * How much do_log() issuing the supplied Log_request shall contribute to #m_pending_logs_sz.</span></div>
<div class="line"><a id="l00647" name="l00647"></a><span class="lineno">  647</span><span class="comment">   * Log_request in this case essentially just describes the `msg` and `metadata` args to do_log().</span></div>
<div class="line"><a id="l00648" name="l00648"></a><span class="lineno">  648</span><span class="comment">   * See discussion of throttling algorithm in Impl section of class doc header.</span></div>
<div class="line"><a id="l00649" name="l00649"></a><span class="lineno">  649</span><span class="comment">   *</span></div>
<div class="line"><a id="l00650" name="l00650"></a><span class="lineno">  650</span><span class="comment">   * @param log_request</span></div>
<div class="line"><a id="l00651" name="l00651"></a><span class="lineno">  651</span><span class="comment">   *        See do_log(): essentially filled-out with `msg`- and `metadata`-derived info.</span></div>
<div class="line"><a id="l00652" name="l00652"></a><span class="lineno">  652</span><span class="comment">   *        The value of Log_request::m_throttling_begins is ignored in the computation (it would not affect it</span></div>
<div class="line"><a id="l00653" name="l00653"></a><span class="lineno">  653</span><span class="comment">   *        anyway), but the other fields must be set.</span></div>
<div class="line"><a id="l00654" name="l00654"></a><span class="lineno">  654</span><span class="comment">   * @return Positive value.  (Informally: we&#39;ve observed roughly 200 plus message size as of this writing.)</span></div>
<div class="line"><a id="l00655" name="l00655"></a><span class="lineno">  655</span><span class="comment">   */</span></div>
<div class="line"><a id="l00656" name="l00656"></a><span class="lineno">  656</span>  <span class="keyword">static</span> <span class="keywordtype">size_t</span> <a class="code hl_function" href="classflow_1_1log_1_1Async__file__logger.html#a6d74d81cb726a30f33f4fc106e3be5b6">mem_cost</a>(<span class="keyword">const</span> <a class="code hl_struct" href="structflow_1_1log_1_1Async__file__logger_1_1Log__request.html">Log_request</a>&amp; log_request);</div>
<div class="line"><a id="l00657" name="l00657"></a><span class="lineno">  657</span><span class="comment"></span> </div>
<div class="line"><a id="l00658" name="l00658"></a><span class="lineno">  658</span><span class="comment">  /**</span></div>
<div class="line"><a id="l00659" name="l00659"></a><span class="lineno">  659</span><span class="comment">   * Estimate of memory footprint of the given value, including memory allocated on its behalf -- but</span></div>
<div class="line"><a id="l00660" name="l00660"></a><span class="lineno">  660</span><span class="comment">   * excluding its shallow `sizeof`! -- in bytes.</span></div>
<div class="line"><a id="l00661" name="l00661"></a><span class="lineno">  661</span><span class="comment">   *</span></div>
<div class="line"><a id="l00662" name="l00662"></a><span class="lineno">  662</span><span class="comment">   * @param val</span></div>
<div class="line"><a id="l00663" name="l00663"></a><span class="lineno">  663</span><span class="comment">   *        Value.</span></div>
<div class="line"><a id="l00664" name="l00664"></a><span class="lineno">  664</span><span class="comment">   * @return See above.</span></div>
<div class="line"><a id="l00665" name="l00665"></a><span class="lineno">  665</span><span class="comment">   */</span></div>
<div class="line"><a id="l00666" name="l00666"></a><span class="lineno">  666</span>  <span class="keyword">static</span> <span class="keywordtype">size_t</span> <a class="code hl_function" href="classflow_1_1log_1_1Async__file__logger.html#a9eff13fef045d9dd58a34d207ff6521e">deep_size</a>(<span class="keyword">const</span> <a class="code hl_struct" href="structflow_1_1log_1_1Async__file__logger_1_1Log__request.html">Log_request</a>&amp; val);</div>
<div class="line"><a id="l00667" name="l00667"></a><span class="lineno">  667</span> </div>
<div class="line"><a id="l00668" name="l00668"></a><span class="lineno">  668</span>  <span class="comment">// Data.</span></div>
<div class="line"><a id="l00669" name="l00669"></a><span class="lineno">  669</span><span class="comment"></span> </div>
<div class="line"><a id="l00670" name="l00670"></a><span class="lineno">  670</span><span class="comment">  /**</span></div>
<div class="line"><a id="l00671" name="l00671"></a><span class="lineno">  671</span><span class="comment">   * Protects throttling algorithm data that require coherence among themselves:</span></div>
<div class="line"><a id="l00672" name="l00672"></a><span class="lineno">  672</span><span class="comment">   * #m_throttling_cfg, #m_pending_logs_sz, #m_throttling_now.  The latter is nevertheless `atomic&lt;&gt;`; see</span></div>
<div class="line"><a id="l00673" name="l00673"></a><span class="lineno">  673</span><span class="comment">   * its doc header as to why.</span></div>
<div class="line"><a id="l00674" name="l00674"></a><span class="lineno">  674</span><span class="comment">   *</span></div>
<div class="line"><a id="l00675" name="l00675"></a><span class="lineno">  675</span><span class="comment">   * ### Perf ###</span></div>
<div class="line"><a id="l00676" name="l00676"></a><span class="lineno">  676</span><span class="comment">   * The critical sections locked by this are extremely small, and should_log() does not have one at all.</span></div>
<div class="line"><a id="l00677" name="l00677"></a><span class="lineno">  677</span><span class="comment">   *</span></div>
<div class="line"><a id="l00678" name="l00678"></a><span class="lineno">  678</span><span class="comment">   * @see Class doc header Impl section for discussion of the throttling algorithm and locking in particular.</span></div>
<div class="line"><a id="l00679" name="l00679"></a><span class="lineno">  679</span><span class="comment">   */</span></div>
<div class="line"><a id="l00680" name="l00680"></a><span class="lineno"><a class="line" href="classflow_1_1log_1_1Async__file__logger.html#a99cd4faff109ef35720fbed9837973dc">  680</a></span>  <span class="keyword">mutable</span> <a class="code hl_typedef" href="classflow_1_1log_1_1Async__file__logger.html#a2f21285253ab0f9a81cf991f99ce6549">Mutex</a> <a class="code hl_variable" href="classflow_1_1log_1_1Async__file__logger.html#a99cd4faff109ef35720fbed9837973dc">m_throttling_mutex</a>;</div>
<div class="line"><a id="l00681" name="l00681"></a><span class="lineno">  681</span><span class="comment"></span> </div>
<div class="line"><a id="l00682" name="l00682"></a><span class="lineno">  682</span><span class="comment">  /// See Throttling_cfg.  Protected by #m_throttling_mutex.</span></div>
<div class="line"><a id="l00683" name="l00683"></a><span class="lineno"><a class="line" href="classflow_1_1log_1_1Async__file__logger.html#aa3d544ab96299a8c2b53b7be485d1a6e">  683</a></span><span class="comment"></span>  <a class="code hl_struct" href="structflow_1_1log_1_1Async__file__logger_1_1Throttling__cfg.html">Throttling_cfg</a> <a class="code hl_variable" href="classflow_1_1log_1_1Async__file__logger.html#aa3d544ab96299a8c2b53b7be485d1a6e">m_throttling_cfg</a>;</div>
<div class="line"><a id="l00684" name="l00684"></a><span class="lineno">  684</span><span class="comment"></span> </div>
<div class="line"><a id="l00685" name="l00685"></a><span class="lineno">  685</span><span class="comment">  /**</span></div>
<div class="line"><a id="l00686" name="l00686"></a><span class="lineno">  686</span><span class="comment">   * Estimate of how much RAM is being used by storing do_log() requests&#39; data (message itself, metadata)</span></div>
<div class="line"><a id="l00687" name="l00687"></a><span class="lineno">  687</span><span class="comment">   * before they&#39;ve been logged to file via `really_log()` (and therefore freed).  Protected by #m_throttling_mutex.</span></div>
<div class="line"><a id="l00688" name="l00688"></a><span class="lineno">  688</span><span class="comment">   *</span></div>
<div class="line"><a id="l00689" name="l00689"></a><span class="lineno">  689</span><span class="comment">   * Each log request&#39;s cost is computed via mem_cost(): do_log() increments this by mem_cost(); then</span></div>
<div class="line"><a id="l00690" name="l00690"></a><span class="lineno">  690</span><span class="comment">   * a corresponding `really_log()` decrements it by that same amount.</span></div>
<div class="line"><a id="l00691" name="l00691"></a><span class="lineno">  691</span><span class="comment">   *</span></div>
<div class="line"><a id="l00692" name="l00692"></a><span class="lineno">  692</span><span class="comment">   * ### Brief discussion ###</span></div>
<div class="line"><a id="l00693" name="l00693"></a><span class="lineno">  693</span><span class="comment">   * If one made this `atomic&lt;size_t&gt;`, and one needed merely the correct updating of #m_pending_logs_sz,</span></div>
<div class="line"><a id="l00694" name="l00694"></a><span class="lineno">  694</span><span class="comment">   * the mutex #m_throttling_mutex would not be necessary: `.fetch_add(mem_cost(...), relaxed)`</span></div>
<div class="line"><a id="l00695" name="l00695"></a><span class="lineno">  695</span><span class="comment">   * and `.fetch_sub(mem_cost(...), relaxed)` would have worked perfectly with no corruption or unexpected</span></div>
<div class="line"><a id="l00696" name="l00696"></a><span class="lineno">  696</span><span class="comment">   * reordering; each read/modify/write op is atomic, and that is sufficient.  Essentially the mutex was needed</span></div>
<div class="line"><a id="l00697" name="l00697"></a><span class="lineno">  697</span><span class="comment">   * only to synchronize subsequent potential assignment of #m_throttling_now.</span></div>
<div class="line"><a id="l00698" name="l00698"></a><span class="lineno">  698</span><span class="comment">   *</span></div>
<div class="line"><a id="l00699" name="l00699"></a><span class="lineno">  699</span><span class="comment">   * @see Class doc header Impl section for discussion of the throttling algorithm and locking in particular.</span></div>
<div class="line"><a id="l00700" name="l00700"></a><span class="lineno">  700</span><span class="comment">   */</span></div>
<div class="line"><a id="l00701" name="l00701"></a><span class="lineno"><a class="line" href="classflow_1_1log_1_1Async__file__logger.html#a7cce9184c2137aa4c2d09894e1aaa7c9">  701</a></span>  <span class="keywordtype">size_t</span> <a class="code hl_variable" href="classflow_1_1log_1_1Async__file__logger.html#a7cce9184c2137aa4c2d09894e1aaa7c9">m_pending_logs_sz</a>;</div>
<div class="line"><a id="l00702" name="l00702"></a><span class="lineno">  702</span><span class="comment"></span> </div>
<div class="line"><a id="l00703" name="l00703"></a><span class="lineno">  703</span><span class="comment">  /**</span></div>
<div class="line"><a id="l00704" name="l00704"></a><span class="lineno">  704</span><span class="comment">   * Contains the output of the always-on throttling algorithm; namely</span></div>
<div class="line"><a id="l00705" name="l00705"></a><span class="lineno">  705</span><span class="comment">   * `true` if currently should_log() shall return `false` due to too-much-RAM-being-used; `false` otherwise.</span></div>
<div class="line"><a id="l00706" name="l00706"></a><span class="lineno">  706</span><span class="comment">   * It starts at `false`; when `m_throttling_cfg.m_hi_limit` is crossed (by #m_pending_logs_sz) going up</span></div>
<div class="line"><a id="l00707" name="l00707"></a><span class="lineno">  707</span><span class="comment">   * in do_log(), it is made equal to `true`; when reaching 0 it is made equal to `false`.</span></div>
<div class="line"><a id="l00708" name="l00708"></a><span class="lineno">  708</span><span class="comment">   *</span></div>
<div class="line"><a id="l00709" name="l00709"></a><span class="lineno">  709</span><span class="comment">   * Protected by #m_throttling_mutex.  *Additionally* it is `atomic`, so that should_log() can read it</span></div>
<div class="line"><a id="l00710" name="l00710"></a><span class="lineno">  710</span><span class="comment">   * without locking.  should_log() does not care about the other items protected by the mutex, and it for</span></div>
<div class="line"><a id="l00711" name="l00711"></a><span class="lineno">  711</span><span class="comment">   * functional purposes does not care about inter-thread volatility due to `relaxed`-order access to this</span></div>
<div class="line"><a id="l00712" name="l00712"></a><span class="lineno">  712</span><span class="comment">   * flag around the rare occasions when its value actually changes.</span></div>
<div class="line"><a id="l00713" name="l00713"></a><span class="lineno">  713</span><span class="comment">   *</span></div>
<div class="line"><a id="l00714" name="l00714"></a><span class="lineno">  714</span><span class="comment">   * @see Class doc header Impl section for discussion of the throttling algorithm and locking in particular.</span></div>
<div class="line"><a id="l00715" name="l00715"></a><span class="lineno">  715</span><span class="comment">   *</span></div>
<div class="line"><a id="l00716" name="l00716"></a><span class="lineno">  716</span><span class="comment">   * At least for logging purposes we do want to detect when it *changes* from `false` to `true` and vice versa;</span></div>
<div class="line"><a id="l00717" name="l00717"></a><span class="lineno">  717</span><span class="comment">   * this occurs only the 1st time it reaches `hi_limit` since it was last 0; and similarly the 1st time it reaches</span></div>
<div class="line"><a id="l00718" name="l00718"></a><span class="lineno">  718</span><span class="comment">   * 0 since it was last `&gt;= hi_limit`.</span></div>
<div class="line"><a id="l00719" name="l00719"></a><span class="lineno">  719</span><span class="comment">   */</span></div>
<div class="line"><a id="l00720" name="l00720"></a><span class="lineno"><a class="line" href="classflow_1_1log_1_1Async__file__logger.html#aa13ef30bc2d66758c29c31dc76a130aa">  720</a></span>  std::atomic&lt;bool&gt; <a class="code hl_variable" href="classflow_1_1log_1_1Async__file__logger.html#aa13ef30bc2d66758c29c31dc76a130aa">m_throttling_now</a>;</div>
<div class="line"><a id="l00721" name="l00721"></a><span class="lineno">  721</span><span class="comment"></span> </div>
<div class="line"><a id="l00722" name="l00722"></a><span class="lineno">  722</span><span class="comment">  /**</span></div>
<div class="line"><a id="l00723" name="l00723"></a><span class="lineno">  723</span><span class="comment">   * Whether the throttling-based-on-pending-logs-memory-used feature is currently active or not. As explained</span></div>
<div class="line"><a id="l00724" name="l00724"></a><span class="lineno">  724</span><span class="comment">   * in detail in Throttling section in class doc header, this is queried only in should_log() and only as a</span></div>
<div class="line"><a id="l00725" name="l00725"></a><span class="lineno">  725</span><span class="comment">   * gate to access the results of the always-on throttling algorithm: #m_throttling_now.  That algorithm,</span></div>
<div class="line"><a id="l00726" name="l00726"></a><span class="lineno">  726</span><span class="comment">   * whose data reside in other `m_throttling_*` and #m_pending_logs_sz, is always active; but this</span></div>
<div class="line"><a id="l00727" name="l00727"></a><span class="lineno">  727</span><span class="comment">   * `m_throttling_active` flag determines whether that algorithm&#39;s output #m_throttling_now is used or</span></div>
<div class="line"><a id="l00728" name="l00728"></a><span class="lineno">  728</span><span class="comment">   * ignored by should_log().</span></div>
<div class="line"><a id="l00729" name="l00729"></a><span class="lineno">  729</span><span class="comment">   *</span></div>
<div class="line"><a id="l00730" name="l00730"></a><span class="lineno">  730</span><span class="comment">   * It is atomic, and accessed with `relaxed` order only, due to being potentially frequently accessed in</span></div>
<div class="line"><a id="l00731" name="l00731"></a><span class="lineno">  731</span><span class="comment">   * the very-often-called should_log().  Since independent of the other state, it does not need mutex protection.</span></div>
<div class="line"><a id="l00732" name="l00732"></a><span class="lineno">  732</span><span class="comment">   */</span></div>
<div class="line"><a id="l00733" name="l00733"></a><span class="lineno"><a class="line" href="classflow_1_1log_1_1Async__file__logger.html#a5bbad8cea27134844e73daff014cc82a">  733</a></span>  std::atomic&lt;bool&gt; <a class="code hl_variable" href="classflow_1_1log_1_1Async__file__logger.html#a5bbad8cea27134844e73daff014cc82a">m_throttling_active</a>;</div>
<div class="line"><a id="l00734" name="l00734"></a><span class="lineno">  734</span><span class="comment"></span> </div>
<div class="line"><a id="l00735" name="l00735"></a><span class="lineno">  735</span><span class="comment">  /**</span></div>
<div class="line"><a id="l00736" name="l00736"></a><span class="lineno">  736</span><span class="comment">   * This is the `Logger` doing all the real log-writing work (the one stored in Log_context is the</span></div>
<div class="line"><a id="l00737" name="l00737"></a><span class="lineno">  737</span><span class="comment">   * logger-about-logging, `backup_logger_ptr` from ctor args).  In itself it&#39;s a fully functional Logger, but</span></div>
<div class="line"><a id="l00738" name="l00738"></a><span class="lineno">  738</span><span class="comment">   * its main limitation is all calls between construction and destruction must be performed non-concurrently --</span></div>
<div class="line"><a id="l00739" name="l00739"></a><span class="lineno">  739</span><span class="comment">   * for example from a single thread or boost.asio &quot;strand.&quot;  The way we leverage it is we simply only make</span></div>
<div class="line"><a id="l00740" name="l00740"></a><span class="lineno">  740</span><span class="comment">   * log-file-related calls (especially Serial_file_logger::do_log() but also</span></div>
<div class="line"><a id="l00741" name="l00741"></a><span class="lineno">  741</span><span class="comment">   * Serial_file_logger::log_flush_and_reopen()) from within #m_async_worker-posted tasks (in other words from</span></div>
<div class="line"><a id="l00742" name="l00742"></a><span class="lineno">  742</span><span class="comment">   * the thread #m_async_worker starts at construction).</span></div>
<div class="line"><a id="l00743" name="l00743"></a><span class="lineno">  743</span><span class="comment">   *</span></div>
<div class="line"><a id="l00744" name="l00744"></a><span class="lineno">  744</span><span class="comment">   * ### Design rationale ###</span></div>
<div class="line"><a id="l00745" name="l00745"></a><span class="lineno">  745</span><span class="comment">   * What&#39;s the point of Serial_file_logger?  Why not just have all those data and logic (storing the `ofstream`, etc.)</span></div>
<div class="line"><a id="l00746" name="l00746"></a><span class="lineno">  746</span><span class="comment">   * directly in Async_file_logger?  Answer: That&#39;s how it was originally.  The cumulative amount of state and logic</span></div>
<div class="line"><a id="l00747" name="l00747"></a><span class="lineno">  747</span><span class="comment">   * is the same; and there&#39;s no real usefulness for Serial_file_logger as a stand-alone Logger for general users;</span></div>
<div class="line"><a id="l00748" name="l00748"></a><span class="lineno">  748</span><span class="comment">   * so in and of itself splitting it out only adds a bit of coding overhead but is otherwise the same.  So why do it?</span></div>
<div class="line"><a id="l00749" name="l00749"></a><span class="lineno">  749</span><span class="comment">   * Answer:</span></div>
<div class="line"><a id="l00750" name="l00750"></a><span class="lineno">  750</span><span class="comment">   *</span></div>
<div class="line"><a id="l00751" name="l00751"></a><span class="lineno">  751</span><span class="comment">   * The reason we split it off was the following: We wanted to sometimes log to the real file from within the</span></div>
<div class="line"><a id="l00752" name="l00752"></a><span class="lineno">  752</span><span class="comment">   * #m_async_worker thread; namely to mark with a pair of log messages that a file has been rotated.  It was possible</span></div>
<div class="line"><a id="l00753" name="l00753"></a><span class="lineno">  753</span><span class="comment">   * to do this via direct calls to a would-be `impl_do_log()` (which is do_log() but already from the worker thread),</span></div>
<div class="line"><a id="l00754" name="l00754"></a><span class="lineno">  754</span><span class="comment">   * but then one couldn&#39;t use the standard `FLOW_LOG_*()` statements to do it; this was both inconvenient and difficult</span></div>
<div class="line"><a id="l00755" name="l00755"></a><span class="lineno">  755</span><span class="comment">   * to maintain over time (we predicted).  At that point it made sense that really Async_file_logger *is*</span></div>
<div class="line"><a id="l00756" name="l00756"></a><span class="lineno">  756</span><span class="comment">   * a would-be Serial_file_logger (one that works from one thread) with the creation of the one thread -- and other</span></div>
<div class="line"><a id="l00757" name="l00757"></a><span class="lineno">  757</span><span class="comment">   * such goodies -- added on top.  With that, `FLOW_LOG_SET_LOGGER(m_serial_logger)` + `FLOW_LOG_INFO()` trivially logs</span></div>
<div class="line"><a id="l00758" name="l00758"></a><span class="lineno">  758</span><span class="comment">   * to the file (as long as it&#39;s done from the worker thread), accomplishing that goal; and furthermore it makes</span></div>
<div class="line"><a id="l00759" name="l00759"></a><span class="lineno">  759</span><span class="comment">   * logical sense in terms of overall design.  The latter fact I (ygoldfel) would say is the best justification; and</span></div>
<div class="line"><a id="l00760" name="l00760"></a><span class="lineno">  760</span><span class="comment">   * the desire for `*this` to log to the file, itself, was the triggering use case.</span></div>
<div class="line"><a id="l00761" name="l00761"></a><span class="lineno">  761</span><span class="comment">   *</span></div>
<div class="line"><a id="l00762" name="l00762"></a><span class="lineno">  762</span><span class="comment">   * @todo Async_file_logger::m_serial_logger (and likely a few other similar `unique_ptr` members of other</span></div>
<div class="line"><a id="l00763" name="l00763"></a><span class="lineno">  763</span><span class="comment">   * classes) would be slightly nicer as an `std::optional&lt;&gt;` instead of `unique_ptr`.  `optional` was not</span></div>
<div class="line"><a id="l00764" name="l00764"></a><span class="lineno">  764</span><span class="comment">   * in STL back in the day and either did not exist or did not catch our attention back in the day.  `unique_ptr`</span></div>
<div class="line"><a id="l00765" name="l00765"></a><span class="lineno">  765</span><span class="comment">   * in situations like this is fine but uses the heap more.</span></div>
<div class="line"><a id="l00766" name="l00766"></a><span class="lineno">  766</span><span class="comment">   */</span></div>
<div class="line"><a id="l00767" name="l00767"></a><span class="lineno"><a class="line" href="classflow_1_1log_1_1Async__file__logger.html#a5c06c592797c70077fc02c98ebf231da">  767</a></span>  boost::movelib::unique_ptr&lt;Serial_file_logger&gt; <a class="code hl_variable" href="classflow_1_1log_1_1Async__file__logger.html#a5c06c592797c70077fc02c98ebf231da">m_serial_logger</a>;</div>
<div class="line"><a id="l00768" name="l00768"></a><span class="lineno">  768</span><span class="comment"></span> </div>
<div class="line"><a id="l00769" name="l00769"></a><span class="lineno">  769</span><span class="comment">  /**</span></div>
<div class="line"><a id="l00770" name="l00770"></a><span class="lineno">  770</span><span class="comment">   * The thread (1-thread pool, technically) in charge of all #m_serial_logger I/O operations including writes</span></div>
<div class="line"><a id="l00771" name="l00771"></a><span class="lineno">  771</span><span class="comment">   * to file.  Thread starts at construction of `*this`; ends (and is synchronously joined) at</span></div>
<div class="line"><a id="l00772" name="l00772"></a><span class="lineno">  772</span><span class="comment">   * destruction of `*this` (by means of delegating to #m_async_worker destructor).</span></div>
<div class="line"><a id="l00773" name="l00773"></a><span class="lineno">  773</span><span class="comment">   */</span></div>
<div class="line"><a id="l00774" name="l00774"></a><span class="lineno"><a class="line" href="classflow_1_1log_1_1Async__file__logger.html#a2cbf044c57201ea66c2c7fa0026846eb">  774</a></span>  <a class="code hl_class" href="classflow_1_1async_1_1Single__thread__task__loop.html">async::Single_thread_task_loop</a> <a class="code hl_variable" href="classflow_1_1log_1_1Async__file__logger.html#a2cbf044c57201ea66c2c7fa0026846eb">m_async_worker</a>;</div>
<div class="line"><a id="l00775" name="l00775"></a><span class="lineno">  775</span><span class="comment"></span> </div>
<div class="line"><a id="l00776" name="l00776"></a><span class="lineno">  776</span><span class="comment">  /**</span></div>
<div class="line"><a id="l00777" name="l00777"></a><span class="lineno">  777</span><span class="comment">   * Signal set which we may or may not be using to trap SIGHUP in order to auto-fire</span></div>
<div class="line"><a id="l00778" name="l00778"></a><span class="lineno">  778</span><span class="comment">   * `m_serial_logger-&gt;log_flush_and_reopen()` in #m_async_worker.  `add()` is called on it at init iff [sic]</span></div>
<div class="line"><a id="l00779" name="l00779"></a><span class="lineno">  779</span><span class="comment">   * that feature is enabled by the user via ctor arg `capture_rotate_signals_internally`.  Otherwise this object</span></div>
<div class="line"><a id="l00780" name="l00780"></a><span class="lineno">  780</span><span class="comment">   * just does nothing `*this` lifetime.</span></div>
<div class="line"><a id="l00781" name="l00781"></a><span class="lineno">  781</span><span class="comment">   */</span></div>
<div class="line"><a id="l00782" name="l00782"></a><span class="lineno"><a class="line" href="classflow_1_1log_1_1Async__file__logger.html#a7192ad2ad8de3014dba6805cd60d5166">  782</a></span>  <a class="code hl_typedef" href="classflow_1_1log_1_1Async__file__logger.html#aa452be34d366b80024eaed98d47b987f">Signal_set</a> <a class="code hl_variable" href="classflow_1_1log_1_1Async__file__logger.html#a7192ad2ad8de3014dba6805cd60d5166">m_signal_set</a>;</div>
<div class="line"><a id="l00783" name="l00783"></a><span class="lineno">  783</span>}; <span class="comment">// class Async_file_logger</span></div>
<div class="line"><a id="l00784" name="l00784"></a><span class="lineno">  784</span> </div>
<div class="line"><a id="l00785" name="l00785"></a><span class="lineno">  785</span>} <span class="comment">// namespace flow::log</span></div>
<div class="ttc" id="aclassflow_1_1async_1_1Single__thread__task__loop_html"><div class="ttname"><a href="classflow_1_1async_1_1Single__thread__task__loop.html">flow::async::Single_thread_task_loop</a></div><div class="ttdoc">A Concurrent_task_loop-related adapter-style class that represents a single-thread task loop; essenti...</div><div class="ttdef"><b>Definition:</b> <a href="single__thread__task__loop_8hpp_source.html#l00075">single_thread_task_loop.hpp:78</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Async__file__logger_html"><div class="ttname"><a href="classflow_1_1log_1_1Async__file__logger.html">flow::log::Async_file_logger</a></div><div class="ttdoc">An implementation of Logger that logs messages to a given file-system path but never blocks any loggi...</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8hpp_source.html#l00358">async_file_logger.hpp:361</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Async__file__logger_html_a10757ede565842d0faebf50bc1424610"><div class="ttname"><a href="classflow_1_1log_1_1Async__file__logger.html#a10757ede565842d0faebf50bc1424610">flow::log::Async_file_logger::Lock_guard</a></div><div class="ttdeci">flow::util::Lock_guard&lt; Mutex &gt; Lock_guard</div><div class="ttdoc">Short-hand for Mutex lock.</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8hpp_source.html#l00567">async_file_logger.hpp:567</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Async__file__logger_html_a2cbf044c57201ea66c2c7fa0026846eb"><div class="ttname"><a href="classflow_1_1log_1_1Async__file__logger.html#a2cbf044c57201ea66c2c7fa0026846eb">flow::log::Async_file_logger::m_async_worker</a></div><div class="ttdeci">async::Single_thread_task_loop m_async_worker</div><div class="ttdoc">The thread (1-thread pool, technically) in charge of all m_serial_logger I/O operations including wri...</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8hpp_source.html#l00774">async_file_logger.hpp:774</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Async__file__logger_html_a2f21285253ab0f9a81cf991f99ce6549"><div class="ttname"><a href="classflow_1_1log_1_1Async__file__logger.html#a2f21285253ab0f9a81cf991f99ce6549">flow::log::Async_file_logger::Mutex</a></div><div class="ttdeci">flow::util::Mutex_non_recursive Mutex</div><div class="ttdoc">Short-hand for m_throttling_mutex type.</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8hpp_source.html#l00564">async_file_logger.hpp:564</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Async__file__logger_html_a4b6dcf5c791e32c517c41c935fba29a4"><div class="ttname"><a href="classflow_1_1log_1_1Async__file__logger.html#a4b6dcf5c791e32c517c41c935fba29a4">flow::log::Async_file_logger::m_config</a></div><div class="ttdeci">Config *const m_config</div><div class="ttdoc">Reference to the config object passed to constructor.</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8hpp_source.html#l00558">async_file_logger.hpp:558</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Async__file__logger_html_a541843c3b49c59a70aad70d8ab984188"><div class="ttname"><a href="classflow_1_1log_1_1Async__file__logger.html#a541843c3b49c59a70aad70d8ab984188">flow::log::Async_file_logger::on_rotate_signal</a></div><div class="ttdeci">void on_rotate_signal(const Error_code &amp;sys_err_code, int sig_number)</div><div class="ttdoc">SIGHUP/equivalent handler for the optional feature capture_rotate_signals_internally in constructor.</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8cpp_source.html#l00209">async_file_logger.cpp:209</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Async__file__logger_html_a5bbad8cea27134844e73daff014cc82a"><div class="ttname"><a href="classflow_1_1log_1_1Async__file__logger.html#a5bbad8cea27134844e73daff014cc82a">flow::log::Async_file_logger::m_throttling_active</a></div><div class="ttdeci">std::atomic&lt; bool &gt; m_throttling_active</div><div class="ttdoc">Whether the throttling-based-on-pending-logs-memory-used feature is currently active or not.</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8hpp_source.html#l00733">async_file_logger.hpp:733</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Async__file__logger_html_a5c06c592797c70077fc02c98ebf231da"><div class="ttname"><a href="classflow_1_1log_1_1Async__file__logger.html#a5c06c592797c70077fc02c98ebf231da">flow::log::Async_file_logger::m_serial_logger</a></div><div class="ttdeci">boost::movelib::unique_ptr&lt; Serial_file_logger &gt; m_serial_logger</div><div class="ttdoc">This is the Logger doing all the real log-writing work (the one stored in Log_context is the logger-a...</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8hpp_source.html#l00767">async_file_logger.hpp:767</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Async__file__logger_html_a6d74d81cb726a30f33f4fc106e3be5b6"><div class="ttname"><a href="classflow_1_1log_1_1Async__file__logger.html#a6d74d81cb726a30f33f4fc106e3be5b6">flow::log::Async_file_logger::mem_cost</a></div><div class="ttdeci">static size_t mem_cost(const Log_request &amp;log_request)</div><div class="ttdoc">How much do_log() issuing the supplied Log_request shall contribute to m_pending_logs_sz.</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8cpp_source.html#l00439">async_file_logger.cpp:439</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Async__file__logger_html_a7192ad2ad8de3014dba6805cd60d5166"><div class="ttname"><a href="classflow_1_1log_1_1Async__file__logger.html#a7192ad2ad8de3014dba6805cd60d5166">flow::log::Async_file_logger::m_signal_set</a></div><div class="ttdeci">Signal_set m_signal_set</div><div class="ttdoc">Signal set which we may or may not be using to trap SIGHUP in order to auto-fire m_serial_logger-&gt;log...</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8hpp_source.html#l00782">async_file_logger.hpp:782</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Async__file__logger_html_a7cce9184c2137aa4c2d09894e1aaa7c9"><div class="ttname"><a href="classflow_1_1log_1_1Async__file__logger.html#a7cce9184c2137aa4c2d09894e1aaa7c9">flow::log::Async_file_logger::m_pending_logs_sz</a></div><div class="ttdeci">size_t m_pending_logs_sz</div><div class="ttdoc">Estimate of how much RAM is being used by storing do_log() requests' data (message itself,...</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8hpp_source.html#l00701">async_file_logger.hpp:701</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Async__file__logger_html_a83cff0d6857a8295e41f90d5e9cab711"><div class="ttname"><a href="classflow_1_1log_1_1Async__file__logger.html#a83cff0d6857a8295e41f90d5e9cab711">flow::log::Async_file_logger::throttling_active</a></div><div class="ttdeci">bool throttling_active() const</div><div class="ttdoc">Whether the throttling feature is currently in effect.</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8cpp_source.html#l00121">async_file_logger.cpp:121</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Async__file__logger_html_a99cd4faff109ef35720fbed9837973dc"><div class="ttname"><a href="classflow_1_1log_1_1Async__file__logger.html#a99cd4faff109ef35720fbed9837973dc">flow::log::Async_file_logger::m_throttling_mutex</a></div><div class="ttdeci">Mutex m_throttling_mutex</div><div class="ttdoc">Protects throttling algorithm data that require coherence among themselves: m_throttling_cfg,...</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8hpp_source.html#l00680">async_file_logger.hpp:680</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Async__file__logger_html_a9eff13fef045d9dd58a34d207ff6521e"><div class="ttname"><a href="classflow_1_1log_1_1Async__file__logger.html#a9eff13fef045d9dd58a34d207ff6521e">flow::log::Async_file_logger::deep_size</a></div><div class="ttdeci">static size_t deep_size(const Log_request &amp;val)</div><div class="ttdoc">Estimate of memory footprint of the given value, including memory allocated on its behalf – but exclu...</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8cpp_source.html#l00457">async_file_logger.cpp:457</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Async__file__logger_html_aa13ef30bc2d66758c29c31dc76a130aa"><div class="ttname"><a href="classflow_1_1log_1_1Async__file__logger.html#aa13ef30bc2d66758c29c31dc76a130aa">flow::log::Async_file_logger::m_throttling_now</a></div><div class="ttdeci">std::atomic&lt; bool &gt; m_throttling_now</div><div class="ttdoc">Contains the output of the always-on throttling algorithm; namely true if currently should_log() shal...</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8hpp_source.html#l00720">async_file_logger.hpp:720</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Async__file__logger_html_aa3d544ab96299a8c2b53b7be485d1a6e"><div class="ttname"><a href="classflow_1_1log_1_1Async__file__logger.html#aa3d544ab96299a8c2b53b7be485d1a6e">flow::log::Async_file_logger::m_throttling_cfg</a></div><div class="ttdeci">Throttling_cfg m_throttling_cfg</div><div class="ttdoc">See Throttling_cfg. Protected by m_throttling_mutex.</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8hpp_source.html#l00683">async_file_logger.hpp:683</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Async__file__logger_html_aa452be34d366b80024eaed98d47b987f"><div class="ttname"><a href="classflow_1_1log_1_1Async__file__logger.html#aa452be34d366b80024eaed98d47b987f">flow::log::Async_file_logger::Signal_set</a></div><div class="ttdeci">boost::asio::signal_set Signal_set</div><div class="ttdoc">Short-hand for a signal set.</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8hpp_source.html#l00570">async_file_logger.hpp:570</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Async__file__logger_html_aa557c0f55c1044161acc8fb54c115a3e"><div class="ttname"><a href="classflow_1_1log_1_1Async__file__logger.html#aa557c0f55c1044161acc8fb54c115a3e">flow::log::Async_file_logger::do_log</a></div><div class="ttdeci">void do_log(Msg_metadata *metadata, util::String_view msg) override</div><div class="ttdoc">Implements interface method by asynchronously logging the message and some subset of the metadata in ...</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8cpp_source.html#l00242">async_file_logger.cpp:242</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Async__file__logger_html_aaaf956d63042cbc0800680996adabfa2"><div class="ttname"><a href="classflow_1_1log_1_1Async__file__logger.html#aaaf956d63042cbc0800680996adabfa2">flow::log::Async_file_logger::log_flush_and_reopen</a></div><div class="ttdeci">void log_flush_and_reopen(bool async=true)</div><div class="ttdoc">Causes the log at the file-system path to be flushed/closed (if needed) and re-opened; this will happ...</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8cpp_source.html#l00497">async_file_logger.cpp:497</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Async__file__logger_html_ac2080e8abfc2cd9580c84626ae205010"><div class="ttname"><a href="classflow_1_1log_1_1Async__file__logger.html#ac2080e8abfc2cd9580c84626ae205010">flow::log::Async_file_logger::throttling_cfg</a></div><div class="ttdeci">Throttling_cfg throttling_cfg() const</div><div class="ttdoc">Accessor returning a copy of the current set of throttling knobs.</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8cpp_source.html#l00115">async_file_logger.cpp:115</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Async__file__logger_html_ad139ac22e5953e52e03648860a15e3fd"><div class="ttname"><a href="classflow_1_1log_1_1Async__file__logger.html#ad139ac22e5953e52e03648860a15e3fd">flow::log::Async_file_logger::should_log</a></div><div class="ttdeci">bool should_log(Sev sev, const Component &amp;component) const override</div><div class="ttdoc">Implements interface method by returning true if the severity and component (which is allowed to be n...</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8cpp_source.html#l00511">async_file_logger.cpp:511</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Async__file__logger_html_ae48ec685cc9951a37bb670dd92fe1f4e"><div class="ttname"><a href="classflow_1_1log_1_1Async__file__logger.html#ae48ec685cc9951a37bb670dd92fe1f4e">flow::log::Async_file_logger::~Async_file_logger</a></div><div class="ttdeci">~Async_file_logger() override</div><div class="ttdoc">Flushes out anything buffered, returns resources/closes output file(s); then returns.</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8cpp_source.html#l00177">async_file_logger.cpp:177</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Async__file__logger_html_aec2b1796c81b020cacea493e21e19562"><div class="ttname"><a href="classflow_1_1log_1_1Async__file__logger.html#aec2b1796c81b020cacea493e21e19562">flow::log::Async_file_logger::Async_file_logger</a></div><div class="ttdeci">Async_file_logger(Logger *backup_logger_ptr, Config *config, const fs::path &amp;log_path, bool capture_rotate_signals_internally)</div><div class="ttdoc">Constructs logger to subsequently log to the given file-system path.</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8cpp_source.html#l00032">async_file_logger.cpp:32</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Async__file__logger_html_afd773546633aec017f2041feb3a75dd3"><div class="ttname"><a href="classflow_1_1log_1_1Async__file__logger.html#afd773546633aec017f2041feb3a75dd3">flow::log::Async_file_logger::logs_asynchronously</a></div><div class="ttdeci">bool logs_asynchronously() const override</div><div class="ttdoc">Implements interface method by returning true, indicating that this Logger may need the contents of *...</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8cpp_source.html#l00542">async_file_logger.cpp:542</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Component_html"><div class="ttname"><a href="classflow_1_1log_1_1Component.html">flow::log::Component</a></div><div class="ttdoc">A light-weight class, each object storing a component payload encoding an enum value from enum type o...</div><div class="ttdef"><b>Definition:</b> <a href="log_8hpp_source.html#l00839">log.hpp:840</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Config_html"><div class="ttname"><a href="classflow_1_1log_1_1Config.html">flow::log::Config</a></div><div class="ttdoc">Class used to configure the filtering and logging behavior of Loggers; its use in your custom Loggers...</div><div class="ttdef"><b>Definition:</b> <a href="config_8hpp_source.html#l00316">config.hpp:317</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Log__context_html"><div class="ttname"><a href="classflow_1_1log_1_1Log__context.html">flow::log::Log_context</a></div><div class="ttdoc">Convenience class that simply stores a Logger and/or Component passed into a constructor; and returns...</div><div class="ttdef"><b>Definition:</b> <a href="log_8hpp_source.html#l01609">log.hpp:1610</a></div></div>
<div class="ttc" id="aclassflow_1_1log_1_1Logger_html"><div class="ttname"><a href="classflow_1_1log_1_1Logger.html">flow::log::Logger</a></div><div class="ttdoc">Interface that the user should implement, passing the implementing Logger into logging classes (Flow'...</div><div class="ttdef"><b>Definition:</b> <a href="log_8hpp_source.html#l01280">log.hpp:1284</a></div></div>
<div class="ttc" id="adetail_2log__fwd_8hpp_html"><div class="ttname"><a href="detail_2log__fwd_8hpp.html">log_fwd.hpp</a></div></div>
<div class="ttc" id="alog_8hpp_html"><div class="ttname"><a href="log_8hpp.html">log.hpp</a></div></div>
<div class="ttc" id="anamespaceflow_1_1log_html"><div class="ttname"><a href="namespaceflow_1_1log.html">flow::log</a></div><div class="ttdoc">Flow module providing logging functionality.</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8cpp_source.html#l00027">async_file_logger.cpp:28</a></div></div>
<div class="ttc" id="anamespaceflow_1_1log_html_a5c602384e6fe9d7642740ac2fae4ad04"><div class="ttname"><a href="namespaceflow_1_1log.html#a5c602384e6fe9d7642740ac2fae4ad04">flow::log::Sev</a></div><div class="ttdeci">Sev</div><div class="ttdoc">Enumeration containing one of several message severity levels, ordered from highest to lowest.</div><div class="ttdef"><b>Definition:</b> <a href="log__fwd_8hpp_source.html#l00223">log_fwd.hpp:224</a></div></div>
<div class="ttc" id="anamespaceflow_1_1util_html_a5d2247b715da63e4b960909561b90ae7"><div class="ttname"><a href="namespaceflow_1_1util.html#a5d2247b715da63e4b960909561b90ae7">flow::util::Lock_guard</a></div><div class="ttdeci">boost::unique_lock&lt; Mutex &gt; Lock_guard</div><div class="ttdoc">Short-hand for advanced-capability RAII lock guard for any mutex, ensuring exclusive ownership of tha...</div><div class="ttdef"><b>Definition:</b> <a href="util__fwd_8hpp_source.html#l00265">util_fwd.hpp:265</a></div></div>
<div class="ttc" id="anamespaceflow_1_1util_html_add6ade273326f27eaf9bfd170a909626"><div class="ttname"><a href="namespaceflow_1_1util.html#add6ade273326f27eaf9bfd170a909626">flow::util::Mutex_non_recursive</a></div><div class="ttdeci">boost::mutex Mutex_non_recursive</div><div class="ttdoc">Short-hand for non-reentrant, exclusive mutex. (&quot;Reentrant&quot; = one can lock an already-locked-in-that-...</div><div class="ttdef"><b>Definition:</b> <a href="util__fwd_8hpp_source.html#l00215">util_fwd.hpp:215</a></div></div>
<div class="ttc" id="anamespaceflow_1_1util_html_ae4dc52186797094b3040379ff19124c9"><div class="ttname"><a href="namespaceflow_1_1util.html#ae4dc52186797094b3040379ff19124c9">flow::util::String_view</a></div><div class="ttdeci">Basic_string_view&lt; char &gt; String_view</div><div class="ttdoc">Commonly used char-based Basic_string_view. See its doc header.</div><div class="ttdef"><b>Definition:</b> <a href="string__view_8hpp_source.html#l00191">string_view.hpp:191</a></div></div>
<div class="ttc" id="anamespaceflow_html_a29eaaa9d0fac4ce87d8b969222dbed09"><div class="ttname"><a href="namespaceflow.html#a29eaaa9d0fac4ce87d8b969222dbed09">flow::Error_code</a></div><div class="ttdeci">boost::system::error_code Error_code</div><div class="ttdoc">Short-hand for a boost.system error code (which basically encapsulates an integer/enum error code and...</div><div class="ttdef"><b>Definition:</b> <a href="common_8hpp_source.html#l00508">common.hpp:508</a></div></div>
<div class="ttc" id="asingle__thread__task__loop_8hpp_html"><div class="ttname"><a href="single__thread__task__loop_8hpp.html">single_thread_task_loop.hpp</a></div></div>
<div class="ttc" id="astructflow_1_1log_1_1Async__file__logger_1_1Log__request_html"><div class="ttname"><a href="structflow_1_1log_1_1Async__file__logger_1_1Log__request.html">flow::log::Async_file_logger::Log_request</a></div><div class="ttdoc">In addition to the task object (function) itself, these are the data placed onto the queue of m_async...</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8hpp_source.html#l00610">async_file_logger.hpp:611</a></div></div>
<div class="ttc" id="astructflow_1_1log_1_1Async__file__logger_1_1Log__request_html_a43b7a817420a80d955e4acfd0ec10f45"><div class="ttname"><a href="structflow_1_1log_1_1Async__file__logger_1_1Log__request.html#a43b7a817420a80d955e4acfd0ec10f45">flow::log::Async_file_logger::Log_request::m_msg_size</a></div><div class="ttdeci">size_t m_msg_size</div><div class="ttdoc">Number of characters in m_msg_copy pointee string.</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8hpp_source.html#l00618">async_file_logger.hpp:618</a></div></div>
<div class="ttc" id="astructflow_1_1log_1_1Async__file__logger_1_1Log__request_html_a7215d35008420d5c3357df1b06761d64"><div class="ttname"><a href="structflow_1_1log_1_1Async__file__logger_1_1Log__request.html#a7215d35008420d5c3357df1b06761d64">flow::log::Async_file_logger::Log_request::m_metadata</a></div><div class="ttdeci">Msg_metadata * m_metadata</div><div class="ttdoc">Pointer to array of characters comprising a copy of msg passed to do_log(). We must delete it.</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8hpp_source.html#l00621">async_file_logger.hpp:621</a></div></div>
<div class="ttc" id="astructflow_1_1log_1_1Async__file__logger_1_1Log__request_html_a82a13a6d045612578dad42a82de36202"><div class="ttname"><a href="structflow_1_1log_1_1Async__file__logger_1_1Log__request.html#a82a13a6d045612578dad42a82de36202">flow::log::Async_file_logger::Log_request::m_msg_copy</a></div><div class="ttdeci">char * m_msg_copy</div><div class="ttdoc">Pointer to array of characters comprising a copy of msg passed to do_log(). We must delete[] it.</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8hpp_source.html#l00615">async_file_logger.hpp:615</a></div></div>
<div class="ttc" id="astructflow_1_1log_1_1Async__file__logger_1_1Log__request_html_aee7f652b0e17e39d0afdb721bc956cf7"><div class="ttname"><a href="structflow_1_1log_1_1Async__file__logger_1_1Log__request.html#aee7f652b0e17e39d0afdb721bc956cf7">flow::log::Async_file_logger::Log_request::m_throttling_begins</a></div><div class="ttdeci">bool m_throttling_begins</div><div class="ttdoc">Whether this log request was such that its memory footprint (mem_cost()) pushed m_pending_logs_sz fro...</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8hpp_source.html#l00628">async_file_logger.hpp:628</a></div></div>
<div class="ttc" id="astructflow_1_1log_1_1Async__file__logger_1_1Throttling__cfg_html"><div class="ttname"><a href="structflow_1_1log_1_1Async__file__logger_1_1Throttling__cfg.html">flow::log::Async_file_logger::Throttling_cfg</a></div><div class="ttdoc">Controls behavior of the throttling algorithm as described in Async_file_logger doc header Throttling...</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8hpp_source.html#l00376">async_file_logger.hpp:377</a></div></div>
<div class="ttc" id="astructflow_1_1log_1_1Async__file__logger_1_1Throttling__cfg_html_a72a52accb11b29307dad69748e133818"><div class="ttname"><a href="structflow_1_1log_1_1Async__file__logger_1_1Throttling__cfg.html#a72a52accb11b29307dad69748e133818">flow::log::Async_file_logger::Throttling_cfg::S_HI_LIMIT_DEFAULT</a></div><div class="ttdeci">static constexpr uint64_t S_HI_LIMIT_DEFAULT</div><div class="ttdoc">Value of Async_file_logger(...).throttling_cfg().m_hi_limit: default/initial value of m_hi_limit.</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8hpp_source.html#l00393">async_file_logger.hpp:393</a></div></div>
<div class="ttc" id="astructflow_1_1log_1_1Async__file__logger_1_1Throttling__cfg_html_a7a30343e388c65594d06baed25b1aaa9"><div class="ttname"><a href="structflow_1_1log_1_1Async__file__logger_1_1Throttling__cfg.html#a7a30343e388c65594d06baed25b1aaa9">flow::log::Async_file_logger::Throttling_cfg::m_hi_limit</a></div><div class="ttdeci">uint64_t m_hi_limit</div><div class="ttdoc">The throttling algorithm will go from Not-Throttling to Throttling state if and only if the current m...</div><div class="ttdef"><b>Definition:</b> <a href="async__file__logger_8hpp_source.html#l00385">async_file_logger.hpp:385</a></div></div>
<div class="ttc" id="astructflow_1_1log_1_1Msg__metadata_html"><div class="ttname"><a href="structflow_1_1log_1_1Msg__metadata.html">flow::log::Msg_metadata</a></div><div class="ttdoc">Simple data store containing all of the information generated at every logging call site by flow::log...</div><div class="ttdef"><b>Definition:</b> <a href="log_8hpp_source.html#l01040">log.hpp:1041</a></div></div>
<div class="ttc" id="autil__fwd_8hpp_html"><div class="ttname"><a href="util__fwd_8hpp.html">util_fwd.hpp</a></div></div>
</div><!-- fragment --></div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Mar 28 2025 22:55:35 for Flow by&#160;<a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.4
</small></address>
</body>
</html>
